题意给出一个字符串,求串中可能出现的前后缀,从小到大输出。
比如
应该输出
,即
。
有两种写法,一种是字符串hash处理,还有利用KMP的NEXT数组。
hash:
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn = 5e5;
const int p = 233;
typedef unsigned long long ull;
char s[maxn];
ull hash[maxn];
ull base[maxn];
int ans[maxn];
void hash_string(char *s){
hash[0] = s[0]-'a'+1;
base[0] = 1;
int len = strlen(s);
for(int i=1;i<len;++i){
base[i] = base[i-1]*p;
hash[i] = hash[i-1]*p + s[i]-'a'+1;
}
// for(int i=0;i<len;++i){
// printf("%lld %lld%c",base[i], hash[i],(i==len-1)?'\n':' ');
// }
int cnt = 0;
if(s[0] == s[len-1]) ans[cnt++] = 1;
for(int i=2;i<=len;++i){
if(hash[i-1] == hash[len-1]-hash[len-1-i]*base[i]){
ans[cnt++] = i;
}
}
sort(ans,ans+cnt);
for(int i=0;i<cnt;++i)
printf("%d%c", ans[i],(i==cnt-1)?'\n':' ');
}
int main(){
while(~scanf("%s",s)){
hash_string(s);
}
return 0;
}
KMP:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 2e6+100;
int len;
int next[maxn];
char s[maxn];
void getnext(){
len =strlen(s);
int i=0,j=-1;
next[0] = -1;
while(i<len){
if(j == -1 || s[i] == s[j]) next[++i] = ++j;
else j = next[j];
}
for(int i=1;i<=len;++i) printf("%d ",next[i]);
puts("");
}
void getval(int n){ //递归输出
if(next[n] == 0) return;
getval(next[n]);
printf("%d ", next[n]);
}
int main(int argc, char const *argv[])
{
while(~scanf("%s",s)){
getnext();
getval(len);
printf("%d\n", len);
}
return 0;
}