HDU-3948-The Number of Palindromes(回文自动机模板题)

The Number of Palindromes

Problem Description

Now, you are given a string S. We want to know how many distinct substring of S which is palindrome.

Input

The first line of the input contains a single integer T(T<=20), which indicates number of test cases.
Each test case consists of a string S, whose length is less than 100000 and only contains lowercase letters.

Output

For every test case, you should output “Case #k:” first in a single line, where k indicates the case number and starts at 1. Then output the number of distinct substring of S which is palindrome.

Sample Input

3
aaaa
abab
abcd
 

Sample Output

Case #1: 4
Case #2: 4
Case #3: 4
 

解题思路:

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
char s[N];
struct PAM{
	/**
	len[u] : u 节点代表回文串的长度。
	fa[u] : u 节点代表回文串的最长回文后缀代表的节点。
	tran[u][c] : 转移函数,表示在 u 代表的回文串的两端加上字符 c 之后的回文串。
	num[u] : 代表 u 节点代表回文串的回文后缀个数。
	L[i] : 代表原字符串以 i 结尾的回文后缀长度。
	size[u] : u 点代表的回文串的数量。
	**/
    int len[N],fa[N],size[N],num[N],tot,last,trans[N][27],L[N];
    void init(){				// 初始化
        len[0]=0;fa[0]=1;len[1]=-1;fa[1]=0;
        tot=1;last=0;
        memset(trans[1],0,sizeof(trans[1]));
        memset(trans[0],0,sizeof(trans[0]));
    }

    int new_node(int x){		// 建立新节点
        int now=++tot;
        memset(trans[tot],0,sizeof(trans[tot]));
        len[now]=x;
        return now;
    }

    void ins(int c,int n){		// 增量法构造
        int u=last;
        while(s[n-len[u]-1]!=s[n])u=fa[u];
        if(trans[u][c]==0){
            int now=new_node(len[u]+2);
            int v=fa[u];
            while(s[n-len[v]-1]!=s[n])v=fa[v];
            fa[now]=trans[v][c];
            trans[u][c]=now;
            num[now]=num[fa[now]]+1;
        }
        last=trans[u][c];size[last]++;
        L[n]=len[last];
    }

    void build(char *s){
        int len = strlen(s);
        for(int i = 0  ; i < len ; i ++){
            ins(s[i]-'a',i);
        }
    }

}pam;


int main(){
    int n,m;
    int cas = 1;
    cin>>n;
    while(n--){
        cin>>s;
        pam.init();
        pam.build(s);
        cout<<"Case #"<<cas++<<": "<<pam.tot-1<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值