【题目描述】
对于给定的字符串S,我们想知道它有多少个不同的回文子串。
【输入】
一行,一个长度不超过100000的仅小写字母构成的字符串。
【输出】
一个整数,代表不同的回文子串个数。
【输入样例】
abcd
【输出样例】
4
【提示】
有20%的数据,输入字符串的长度不超过1000。
本题有后缀数组的O(n log n)算法,但是既然咱们有回文自动机不是板子题就轻松切掉了嘛。于是又水了一题……
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int mx;
namespace PLD {
char s[maxn];
int trie[maxn][26], num, arr[maxn], sum[maxn], fail[maxn], len[maxn];
int cnt, last, pos;
void init() {
cnt = 1, last = 0;
len[0] = 0, len[1] = -1;
fail[0] = 1, pos = 0;
}
int getfail(int p) {
while(s[pos - len[p] - 1] != s[pos])
p = fail[p];
return p;
}
void add(int x) {
int id = s[x] - 'a';
int p = getfail(last);
if(!trie[p][id]) {
int now = ++cnt;
fail[now] = trie[getfail(fail[p])][id];
len[now] = len[p] + 2;
trie[p][id] = now;
}
last = trie[p][id];
++sum[last];
}
void push_up() {
for(register int i = cnt; i >= 2; --i)
sum[fail[i]] += sum[i];
}
void create() {
int len = strlen(s);
for(register int i = 0; i < len; ++i)
pos = i, add(i);
push_up();
}
}
int main() {
PLD::init();
scanf("%s", PLD::s);
PLD::create();
printf("%d", PLD::cnt - 1);
return 0;
}
rockdu
没有帐号? 立即注册