Live2d Test Env

hiho1602本质不同的回文子串的数量

给定一个字符串S,请统计S的所有子串中,有多少个本质不同的回文字符串?

注意如果两个位置不同的子串满足长度相同且对应字符也都相同,则认为这两个子串本质上是相同的。

Input

一个只包含小写字母的字符串S。

对于30%的数据,S长度不超过100。

对于60%的数据,S长度不超过1000。

对于100%的数据,S长度不超过800000。

Output

回文子串的数量

Sample Input

abbab

Sample Output

5

 

马拉车算法+bkrdhash:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<map>
using namespace std;
#define ULL unsigned long long
const int maxn=2000000+20;
ULL P = 1313131;
ULL sqr[maxn/2],has[maxn/2],V[maxn];

int Laxt[maxn],Next[maxn],cnt=0;
 
const int MOD = 2000007;

bool _insert(ULL Now)
{
       int u=Now%MOD;
       for(int i=Laxt[u];i;i=Next[i]){
        if(V[i]==Now) return true;
       }
       Next[++cnt]=Laxt[u];
       Laxt[u]=cnt;
       V[cnt]=Now;
       return false;
}
int ans=0;void _hash(int x,int y){
    ULL Now=has[y]-has[x-1]*sqr[y-x+1];
    if(!_insert(Now)) ++ans;
} 
void _malacher()
{
    int R=0,Mid=0,Len;
    char c[maxn];
    scanf("%s",c+1);
    Len=strlen(c+1);
    sqr[0]=1;
    for(int i=1;i<=Len;i++){
        sqr[i]=sqr[i-1]*P;
        has[i]=has[i-1]*P+c[i];
    }  
    int r[maxn];
     for(int i=1;i<=Len;++i) {      
        _hash(i,i);
        if(R>i) r[i]=min(r[2*Mid-i],R-i);
        while(i+r[i]+1<=Len&&c[i+r[i]+1]==c[i-r[i]-1]){
            _hash(i-r[i]-1,i+r[i]+1);
            r[i]++;
        }
        if(i+r[i]>R) {
            R=i+r[i];
            Mid=i;
        }
    }
    
    cnt=0;Mid=0;R=0;
    memset(Laxt,0,sizeof(Laxt));
    memset(r,0,sizeof(r));
    for(int i=2;i<=Len;++i) {
        if(R>i) r[i]=min(r[2*Mid-i],R-i+1);
        while(i+r[i]<=Len&&c[i+r[i]]==c[i-r[i]-1]) {
            _hash(i-r[i]-1,i+r[i]);
            ++r[i];
        }
        if(i+r[i]-1>R) {
            R=i+r[i]-1;
            Mid=i;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    _malacher();
    return 0;
}

 

posted @ 2017-10-23 09:08  nimphy  阅读(2728)  评论(0编辑  收藏  举报