zoukankan      html  css  js  c++  java
  • BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)

    BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)

    题面

    自己找去

    HINT

    给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种。我的思路是建立一个广义后缀自动机,对于每个节点记录(size[1]和size[2])分别表示这个节点接受的子串在A中出现多少次,在B中出现多少次,然后(ans=sum_{u=2}^{tot}{size[u][1]*size[u][2]*(node[u].len-node[fa].len)})注意要long long

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int w=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            w=(w<<3)+(w<<1)+ch-48;
            ch=getchar();
        }
        return w*f;
    }
    int n,m;
    int size[800010][3];
    struct SUFFIXAUTOMATON{
        struct Node{
            int fa,len;
            map<int,int> ch;
        }node[800010];
        int lst,tot,root;
        inline void init(){
            lst=tot=root=1;return;
        }
        inline void extend(int now,int id){
            int p=lst;tot++;lst=tot;int np=tot;
            node[np].len=node[p].len+1;size[np][id]=1;
            while(p&&!node[p].ch[now]){
                node[p].ch[now]=np;
                p=node[p].fa;
            }
            if(!p) node[np].fa=1;
            else{
                int q=node[p].ch[now];
                if(node[q].len==node[p].len+1){
                    node[np].fa=q;
                }
                else{
                    int nq=++tot;node[nq]=node[q];
                    node[nq].len=node[p].len+1;
                    node[q].fa=nq;node[np].fa=nq;
                    while(p&&node[p].ch[now]==q){
                        node[p].ch[now]=nq;
                        p=node[p].fa;
                    }
                }
            }
        }
    }SAM;
    int cnt,head[800010];
    struct Edge{
        int from,to,next;
    }edge[1600010];
    inline void addedge(int u,int v){
        cnt++;
        edge[cnt].from=u;
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt;
    }
    char ch[200010];
    inline void dfs(int u){
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;dfs(v);
            size[u][1]+=(long long)size[v][1];
            size[u][2]+=(long long)size[v][2];
        }
        return;
    }
    long long ans;
    signed main(){
        SAM.init();
        for(int i=1;i<=2;i++){
            cin>>ch;int len=strlen(ch);
            for(int j=0;j<len;j++){
                SAM.extend(ch[j]-'a'+1,i);
            }
            SAM.lst=1;
        }
        for(int i=2;i<=SAM.tot;i++){
            addedge(SAM.node[i].fa,i);
        }
        dfs(1);
        //cout<<SAM.tot<<endl; 
        for(int i=2;i<=SAM.tot;i++){
            int f=SAM.node[i].fa;
            //cout<<(long long)size[i][1]*size[i][2]<<" "<<SAM.node[i].len-SAM.node[f].len<<endl;
            long long cur1=(long long)size[i][1]*size[i][2];long long cur2=(long long)SAM.node[i].len-SAM.node[f].len;
            //cout<<cur1<<" "<<cur2<<endl;
            ans+=(long long)cur1*cur2;
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/wenci/p/10639566.html
Copyright © 2011-2022 走看看