zoukankan      html  css  js  c++  java
  • POJ

    题意

    给n个字符串,两两拼接,问拼接后的(n imes n)个字符串中有多少个回文串。

    分析

    将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字符串拼成回文串有三种情况:

    • 未匹配完,反串后缀是回文串。

    • 匹配结束,正串后缀是回文串。

    • 匹配结束,正串等于反串。

    字典树中维护当前位置有多少正串和当前位置有多少后缀为回文串的正串。

    Code

    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    #define ll long long
    using namespace std;
    const int inf=1e9;
    const int mod=1e9+7;
    const int maxn=2e6+10;
    int p[maxn*2],f[2][maxn],len[maxn],sum[2][maxn];
    char s[maxn],t[maxn*2];
    int son[maxn][26],tot;
    ll ans;
    void ins(int dl,int dr){
        int rt=0;
        for(int i=dl;i<=dr;i++){
            if(f[1][i]) sum[1][rt]++;
            if(!son[rt][s[i]-'a']) son[rt][s[i]-'a']=++tot;
            rt=son[rt][s[i]-'a'];
            if(i==dr) sum[0][rt]++;
        }
    }
    void qy(int dl,int dr){
        int rt=0;
        for(int i=dr;i>=dl;i--){
            if(f[0][i]) ans+=sum[0][rt];
            if(!son[rt][s[i]-'a']) return;
            rt=son[rt][s[i]-'a'];
            if(i==dl) ans+=sum[1][rt]+sum[0][rt];
        }
    }
    int mlc(int dl,int dr){
        int m=0,p0=1;p[1]=1;t[++m]='#';
        for(int i=dl;i<=dr;i++){
            t[++m]=s[i];
            t[++m]='#';
        }
        for(int i=2;i<=m;i++){
            int j=min(p[p0]+p0-i,p[2*p0-i]);
            if(i+j<p[p0]+p0){
                p[i]=j;
            }else{
                while(i-j>=1&&i+j<=m&&t[i-j]==t[i+j]) ++j;
                p[i]=j;p0=i;
            }
        }
        for(int i=dl;i<dr;i++){
            if(p[i-dl+2]-1==i-dl+1) f[0][i]=1;
            if(p[dr-2*dl+i+3]-1==dr-i) f[1][i+1]=1;
        }
    }
    int main(){
    	//ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	int n;
    	scanf("%d",&n);int l=1;
    	for(int i=1,m;i<=n;i++){
    		scanf("%d%s",&len[i],s+l);
            mlc(l,l+len[i]-1);
            ins(l,l+len[i]-1);
            l+=len[i];
    	}l=1;
    	for(int i=1;i<=n;i++){
            qy(l,l+len[i]-1);
            l+=len[i];
    	}
    	cout<<ans<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    分布式唯一ID:雪花ID Snowflake .Net版
    jTopo HTML5 Canvas 画图组件
    运用四色建模法进行领域分析
    .netcore 分布式事务CAP2.6之控制台使用
    .netcore 分布式事务CAP2.6 快速入门
    .NetCore从零开始使用Skywalking分布式链路追踪系统
    Docker安装Skywalking APM分布式追踪系统
    ubuntu18.04安装docker
    github超级小白入门攻略
    记录AJAX充电点点滴滴
  • 原文地址:https://www.cnblogs.com/xyq0220/p/11511779.html
Copyright © 2011-2022 走看看