HDU 3948 The Number of Palindromes

The Number of Palindromes

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)

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

题意:

给你一个字符串,问这里面有多少个不同的回文子串。

思路:

回文自动机裸题,我在这里讲一下学回文自动机的fail指针(应该是最难懂得部分了),很多文章都说是节点i失配以后跳转不等于自身的节点i表示的回文串的最长后缀回文串,其实是对的,但是有点难懂,其实要和while (s[n - len[x] - 1] != s[n])相结合来看,跳转完得x进行运算之后,n-len[x] - 1 ~ n中间是一个回文串,也就是前面得所说得不等于自身的节点i的最长后缀回文,然后每一次都是这么找后缀,直到相等之后此时的x的长度+2就是新回文串的长度了。(而fail[n]就是找到的那个回文串的最长回文后缀然后在末尾加上新的字符后的对应的编号,因为getfail,所以最后得到的的还是回文(表述有点不大好,满理解理解))。

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 100010;
int fail[maxn], len[maxn], ch[maxn][26];
char s[maxn];
int getfail(int n, int x) {
    while (s[n - len[x] - 1] != s[n]) x = fail[x];
    return x;
}
int main() {
    int t;
    scanf("%d", &t);
    getchar();
    for (int Case = 1; Case <= t; Case++) {
        memset(len, 0, sizeof(len));
        memset(fail, 0, sizeof(fail));
        memset(ch, 0, sizeof(ch));
        scanf("%s", s + 1);
        int le = strlen(s + 1), cnt = 1, cur = 0;
        len[1] = -1, fail[0] = 1;
        for (int i = 1; i <= le; i++) {
            int now = s[i] - 'a';
            cur = getfail(i, cur);
            if (!ch[cur][now]) {
                len[++cnt] = len[cur] + 2;
                fail[cnt] = ch[getfail(i, fail[cur])][now];
                ch[cur][now] = cnt;
            }
            cur = ch[cur][now];
        }
        printf("Case #%d: %d\n", Case, cnt - 1);
    }
    return 0;
}

你可能感兴趣的:(HDU)