Palindrome automata
With is a string of end node maintains
After adding a node
Is the palindromic sequence in the original all true suffix ( )
Increasing a palindromic sequence update ( mark[num]
)
if (!tree[last][in[i] - 'a']) {
/*operation*/
mark[num] = mark[fail[num]] + 1;
//统计以该节点为结尾的回文串个数
}
//更新last
cnt[i]=mark[last];
Palindrome automaton (PAM)
Interesting
The total number of strings of different nature
Is the number of nodes, blows 1
No. Node
mark[i]=num-1
Palindromes and Super Abilities
CA Loves Palindromic
Maintaining essentially different character string (information from the sub-tree)
For a different nature string
His son can visit his tree
Mark all strings, all statistical information can he subtree
Due to the larger number, about the number of layers deep, so it can traverse backwards
for (int i = 1; i <= n; i++) {
while (in[i - len[last] - 1] != in[i]) last = fail[last];
if (!tree[last][in[i] - 'a']) {
/*operation*/
}
last = tree[last][in[i] - 'a'];
mark[last]++; //标记信息
}
for (int i = num; i; i--) {
mark[fail[i]] += mark[i];
//统计子树信息
}
P3649 palindrome string
Cheerleading rehearsal
Maintain different nature palindrome string (information from the father, ancestor)
set up Tree
Use , maintenance information back palindromic sequence ancestry
void build() {
memset(head, 0, sizeof(int) * (num + 1)); tot = 0;
for (int i = 2; i <= num; i++) AddEdge(fail[i], i);
//建树,用fail边建树
}
int vis[maxn],res[maxn];
void dfs(int now) {
vis[len[now]]++;//维护祖先信息
/*operation 统计答案*/
for (int i = head[now]; i; i = edge[i].next)
dfs(edge[i].v); //dfs
vis[len[now]]--;//回溯
return;
}
HDU6599 I Love Palindrome String
Palindromeness
Maintenance information palindromic sequence has front and rear ends
The establishment of two palindromic sequence
Build a positive, forward, backwards build a
For i
node maintains i
information and node positive sequence palindromic sequence i+1
descending node palindromic sequence information can be combined
struct PAM {
int tree[maxn][26];
int len[maxn], fail[maxn];
int last, num , mark[maxn];
void insert(char* in, int n) {
/*operation*/
}
}pre, suf;
int main() {
scanf("%s", in + 1); in[0] = '#';
int n = strlen(in + 1);
pre.insert(in, n);
//正向建立
reverse(in + 1, in + 1 + n);
suf.insert(in, n);
//反向建立
int ans = 0;
for (int i = 1; i < n; i++) {
ans = max(ans, pre.mark[i] + suf.mark[n-i]);
//两个串信息合并
}
}
P4287 double palindrome
Harry and magic string
Add front-end node
pre,last
Add two markers before and after maintenance
With pre
, for example, when you add a node after
When the string is not the longest palindrome itself after the new node, the node will not affect the newly addedlast
which is is the correct
After the new node itself longest palindrome string to be updatedlast
The update method is
Since only the statistical side, so we count the number of strings of different nature and number of the total of the string is correct
But maintain other information when needed serious consideration
The following is inserted forward:
Similar inserted backwards
void pre_insert(char* in, int i) { //向前添加方法
while (in[i + len[pre] + 1] != in[i]) pre = fail[pre];
if (!tree[pre][in[i] - 'a']) {
len[++num] = len[pre] + 2;
int j = fail[pre];
while (in[i + len[j] + 1] != in[i]) j = fail[j];
fail[num] = tree[j][in[i] - 'a'];
tree[pre][in[i] - 'a'] = num;
mark[num] = mark[fail[num]] + 1; //统计个数
}
pre = tree[pre][in[i] - 'a'];
if (len[pre] == stdr - stdl + 1) last = pre;//当本身变为回文串,更新last
sum = sum + mark[pre]; //维护总个数
}
Victor and String
To optimize the space before stars
As MLE
before, we can use the star chain optimization
To create a dictionary tree star before that the use of chain
Query: traversing all sides, since each point in trie limited number of visits, the complex will not exceed
Assignment: that is built side
struct Edge{
int v;
int w; //w为字母的值
int next;
}edge[maxn];
int head[maxn], tot;
inline void AddEdge(int u, int v, int w) {
edge[++tot].v = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot;
}
int find(int now, int w) { //寻找函数
for (int i = head[now]; i; i = edge[i].next)
if (edge[i].w == w) return edge[i].v;
return 0;
}
for (int i = 1; i <= n; i++) {
while (in[i - len[last] - 1] != in[i]) last = fail[last];
int treenode = find(last, in[i] - 'a');//寻找节点
if (!treenode) {
len[++num] = len[last] + 2;
int j = fail[last];
while (in[i - len[j] - 1] != in[i]) j = fail[j];
fail[num] = find(j, in[i] - 'a');//寻找节点
AddEdge(last, num, in[i] - 'a');//建边
mark[num] = mark[fail[num]] + 1;
treenode = num; //更新节点
}
last = treenode;
cnt[i] = mark[last];
}