Palindrome Mouse Palindrome Automaton

link


Consider the contribution of each point to the answer as the number of nodes on the fail chain and the number of ancestor nodes of the node on the palindrome tree, in addition to itself.
There are two problems with this writing:
1. Duplicate node
2. Time complexity
Consider recurrence, the contribution of this node is its father node contribution + the number of failed chains it extends +1


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;;
const int SZ = 26;///字符集
const int maxn = 1e5 + 6;
struct PAM {
    
    
    struct PamNode{
    
    int fail,trans[SZ],sz,len,num;}pam[maxn];
    int tot;char s[maxn];
    void init() {
    
    
        tot=1;
        pam[0].fail=1;pam[0].len=0;
        pam[1].fail=1;pam[1].len=-1;
        memset(pam[0].trans,0,SZ*sizeof (int));
        memset(pam[1].trans,0,SZ*sizeof (int));
    }
    inline int newnode(int len) {
    
    
        tot++;
        memset(pam[tot].trans,0,SZ*sizeof (int));
        pam[tot].len=len;pam[tot].fail=0;
        pam[tot].sz=0;pam[tot].num=0;
        return tot;
    }
    inline int getfail(int i,int u) {
    
    
        while(s[i-pam[u].len-1]^s[i]) u=pam[u].fail;
        return u;
    }
    inline int append(int i,int u) {
    
    
        int c=s[i]-'a';
        int fa=getfail(i,u);
        u=pam[fa].trans[c];
        if(!u) {
    
    
            int z=newnode(pam[fa].len+2);
            int w=getfail(i,pam[fa].fail);
            pam[z].fail=pam[w].trans[c];
            u=pam[fa].trans[c]=z;///注意这里要后更新,否则上面getfail时可能导致死循环
            pam[z].num=pam[pam[z].fail].num+1;
/*还有一点我们可以指出, 这里属于z代表的回文子串第一次出现, 之前读入s[1,..,i-1]都是没有出现过该回文子串
的, 所以可以维护出每种回文子串第一次出现的索引.只是这里没做而已.
*/
        }
        pam[u].sz++;return u;
    }
    void calu() {
    
    
        for(int i=tot,fail;i>1;i--) {
    
    
            fail=pam[i].fail;
            pam[fail].sz+=pam[i].sz;
        }
    }
    ll ans=0,dp[maxn],vis[maxn];
    int jmp(int u) {
    
    
        int cnt=0;
        while(u>1&&!vis[u]) {
    
    
            vis[u]=1;
            u=pam[u].fail;cnt++;
        }
        return cnt;
    }
    void clr(int u,ll kk) {
    
    
        for(int i=1;i<=kk;i++) {
    
    
            vis[u]=0;
            u=pam[u].fail;
        }
    }

    void dfs(int u,int fa) {
    
    
        ll kk=jmp(u);
        if(u>1) dp[u]=kk-1;
        if(fa>1) dp[u]+=dp[fa]+1;
        ans+=dp[u];
        for(int i=0;i<26;i++) {
    
    
            if(pam[u].trans[i]) {
    
    
                dfs(pam[u].trans[i],u);
            }
        }
        clr(u,kk);
    }
    ll cont() {
    
    
        ans=0;
        dfs(0,0);dfs(1,1);
        return ans;
    }
}pa;
int n,_,cs=0;
int main() {
    
    
    for(scanf("%d",&_);_;_--) {
    
    
        scanf("%s",pa.s+1);
        n=strlen(pa.s+1);
        pa.init();
        for(int i=1,last=0;i<=n;i++) {
    
    
            last=pa.append(i,last);
        }
        printf("Case #%d: %lld\n",++cs,pa.cont());
    }
}

Guess you like

Origin blog.csdn.net/qq_43914084/article/details/106948671