CF 7D 字符串哈希 回文

转自
http://roba.rushcj.com/?p=439
定义k-回文串如下:(1)任何串(包括空串)都是0-回文;
(2)一个长度为n的回文串,若它的前n/2个字符和后n/2个字符都是(k-1)-回文,
则它是k-回文。现给定一个串(长度不超过5,000,000),
设它的每个前缀分别是x-回文,
求所有这些x值的和。
比如abacaba,
”a”是1-回文,
”aba”是2-回文,
”abacaba”是3-回文,故输出6。
将字符串 反转接在后面,然后KMP求解即可
把原串翻转后拼接在原来的串后面,用一个不在字母表中的分隔符隔开的。
然后用KMP里对模式串的预处理那个过程,求出失配以后往前跳的那个指针。
我们从新串最后一个位置开始,每向前跳一次都得到一个回文前缀。
比如有这样一个串 abaaba…..(后面部分省略),拼接后得到
abaaba......#......abaaba
012345......#......6789AB
则最后位置的失配指针为5,由KMP的意义,也就是说(012345) == (6789AB),而同时由我们的翻转操作知(012345)==(BA9876),
故(012345)为一个回文串。从5继续向前跳到2,同理(012)也是回文串。
由上过程可以把全部回文前缀作好标记。然后再从左到右简单地扫描一遍就可以把每个k值计算出来了。
Ps:幸亏CF内存不怎么限制,开了三个1KW的数组啊。。

View Code
#include<cstdio>
#include<cstring>
int n,m;
char b[10000010];
int  p[10000010];
int  d[10000010];
void getp(){
    p[1]=0;
    int i,j=0;
    for(i=2;i<=m;i++){
        while(j>0&&b[j+1]!=b[i]) j=p[j];
        if(b[j+1]==b[i]) j+=1;
        p[i]=j;
    }
}
int main()
{
        scanf("%s",b+1);
        m=strlen(b+1);
        int x=m;
        b[m+1]='#';
        for(int i=1;i<=m;i++)
        {
            b[m+1+i]=b[m+1-i];
        }
        b[2*m+2]='\0';
        m=2*m+1;
        getp();
        int tmp=p[m];
        while(tmp)
        {
            d[tmp]=1;
            tmp=p[tmp];
        }
        __int64 ans=0;
        for(int i=1;i<=m;i++)
        {
            if(d[i]) d[i]=d[i/2]+1;
            ans+=d[i];
        }
        if(ans==0) printf("1\n");
        else     printf("%I64d\n",ans);
    
}

 

 

View Code
一种更简单的方法:哈希
/*
l: s[0]*107^2+s[1]*107+s[2];//从前往后哈希 
r: s[0]+s[1]*107+s[2]*107^2;//从后往前哈希 
*/ 
#include <iostream>
#include <cstdio>
using namespace std;
char s[5000010];
int f[5000010];
int main(){
    scanf("%s", s);
    int l=0, r=0, e=1, ans=0;
    for (int i=0; s[i]; i++){//l,r:两个哈希值,一个从左到右,一个从右到左 
        l=l*103+s[i];
         r=r+s[i]*e; e*=103; 
//         printf("%d %d\n",l,r) ;
        if (l==r)    f[i+1]=f[(i+1)/2]+1;
        ans+=f[i+1];
    }
    cout<<ans<<endl;
}

 

 

 

 

 

 

 

posted @ 2012-06-24 18:13  Because Of You  Views(916)  Comments(0Edit  收藏  举报