回文自动机学习
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
using namespace std;
int T;
char str[maxn];
int ans, n, Idx[300];
struct Node{
int nxt[4], fail, len, trans;
void clear(){
memset(nxt, 0, sizeof nxt);
len = fail = trans = 0;
}
};
int que[maxn], s[maxn];
namespace PAM{
Node st[maxn];
int size, num, last, f[maxn];
void init(){
size = 1, num = 0, last = 0;
st[0].clear(), st[1].clear();
st[0].len = 0; st[1].len = -1;
st[0].fail = st[1].fail = 1;
s[0] = -1;
}
int get_fail(int x){
while(s[num-st[x].len-1] != s[num])
x = st[x].fail;
return x;
}
void Insert(int c){
s[++ num] = c;
int cur = get_fail(last);
if(!st[cur].nxt[c]){
int now = ++ size; st[now].clear();
st[now].len = st[cur].len + 2;
st[now].fail = st[get_fail(st[cur].fail)].nxt[c];
st[cur].nxt[c] = now;
if(st[now].len <= 2)st[now].trans = st[now].fail;
else{
int o = st[cur].trans;
while(s[num-st[o].len-1]!=s[num] || (st[o].len+2)*2 > st[size].len)
o = st[o].fail;
st[now].trans = st[o].nxt[c];
}
}
last = st[cur].nxt[c];
}
}
int main(){
using namespace PAM;
Idx['A'] = 0, Idx['G'] = 1, Idx['C'] = 2, Idx['T'] = 3;
int test;
scanf("%d", &test);
while(test --){
scanf("%s", str+1);
n = strlen(str+1);
init(); ans = n;
for(int i = 1; i <= n; i ++)
Insert(Idx[str[i]]);
for(int i = 2; i <= size; i ++)
if(st[i].len & 1)f[i] = st[i].len;
int head = 0, tail = 0, t;
que[tail ++] = 0;
f[0] = 1;
while(head != tail){
int u = que[head ++];
for(int i = 0; i < 4; i ++){
if(t = st[u].nxt[i]){
f[t] = min(f[u] + 1, st[t].len / 2 - st[st[t].trans].len + f[st[t].trans] + 1);
ans = min(ans, n - st[t].len + f[t]);
que[tail ++] = t;
}
}
}
printf("%d\n", ans);
}
}