1. 程式人生 > >牛客多校第三場 E Sort String(字串hash)

牛客多校第三場 E Sort String(字串hash)

題目描述

Eddy likes to play with string which is a sequence of characters. One day, Eddy has played with a string S for a long time and wonders how could make it more enjoyable. Eddy comes up with following procedure:

1. For each i in [0,|S|-1], let Si be the substring of S starting from i-th character to the end followed by the substring of first i characters of S. Index of string starts from 0.
2. Group up all the Si. Si and Sj will be the same group if and only if Si=Sj.
3. For each group, let Lj be the list of index i in non-decreasing order of Si in this group.
4. Sort all the Lj by lexicographical order.

Eddy can't find any efficient way to compute the final result. As one of his best friend, you come to help him compute the answer!

輸入描述:

Input contains only one line consisting of a string S.

1≤ |S|≤ 106
S only contains lowercase English letters(i.e. ).

輸出描述:

First, output one line containing an integer K indicating the number of lists.
For each following K lines, output each list in lexicographical order.
For each list, output its length followed by the indexes in it separated by a single space.

示例1

輸入

複製

abab

輸出

複製

2
2 0 2
2 1 3

示例2

輸入

複製

deadbeef

輸出

複製

8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7

題目大意:一開始給出一個字串S,定義字串串T[i]=S[i,...,n]+S[1,...,i-1](i=1,...,n)現在要對這n個字串進行分類,將所有相同的串放到一個集合,同時對這幾個集合按下標的字典序進行排序之後輸出。

題目思路:對於這個題,我們可以先將字串S進行拼接,令SS=S+S,這樣每個T[i]=SS[i,...,i+n-1],然後再借助字串hash對SS串進行處理,這樣就可以在O(1)的時間裡求出T[i]的hash值。接著再將hash值相同的串進行分類處理即可。

小小吐槽下,這個題居然卡常數,一開始怕精確度不夠用雙hash寫的,居然T了,後面嘗試了下用unsigned long long自然溢位來處理hash值就過了,還是有點小坑的。-,-

具體實現看程式碼:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) x&-x
#define MP make_pair
#define pb push_back
#define debug(x) cout<<x<<"= "<<x<<endl;
#define FIN freopen("in.txt","r",stdin);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int,int>pii;
typedef pair<ll,ll>pll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll infll=0x3f3f3f3f3f3f3f3f;
const int mod1 = 1e9+7;
const int mod2 = 998244353;
const int MX = 2e6+7;
const int has = 99959;
 

char str[MX];
ull H[MX],P[MX];
unordered_map<ull,int>mp;
void Hash(int n){
    H[0]=P[0]=1;
    for(int i=1;i<=n;i++){
        H[i]=H[i-1]*has+str[i]-'0'+1;
        P[i]=P[i-1]*has;
    }
}
ull get_hash(int l,int r){
    return H[r]-H[l-1]*P[r-l+1];
}
vector<int>ans[MX];

int main(){
    //FIN;
    scanf("%s",str+1);
    int len=strlen(str+1);
    for(int i=len+1;i<=2*len;i++)
        str[i]=str[i-len];
    str[2*len+1]='\0';
    Hash(2*len);
    int num=0;
    for(int i=1;i<=len;i++){
        ull cnt=get_hash(i,i+len-1);
        if(mp[cnt]==0){
            mp[cnt]=++num;
            ans[num].pb(i-1);
        } else{
            ans[mp[cnt]].pb(i-1);
        }
    }
    printf("%d\n",num);
    for(int i=1;i<=num;i++){
        printf("%d ",ans[i].size());
        for(int x:ans[i])
            printf("%d ",x);
        printf("\n");
    }
    return 0;
}