• #552. 【UNR #4】同构判定鸭


    题目描述


    题解

    结论:坏串长度<=n1+n2

    口胡证明:

    把两个图合并,第二个图的标号加上n1,状态可以看作一个长度位n1+n2的向量,转移看作26个矩阵,不同位的不同字母的值不同(随机),基本可以视作哈希值与串一一对应

    称一些串组成的集合为向量空间,一个向量空间的维数等价于线性无关组大小

    每次转移等于把集合U或上U*转移矩阵,如果向量空间里面存在某个向量点乘上一个前n1个为1后n2个为-1的向量非0则对应一个坏串

    每次转移之后的向量空间U1,U2,U3...满足U1⊆U2⊆U3⊆...

    结论:如果集合U⊆集合V那么满足V的维数>U或U=V,因为如果不相等那么V多出来的那部分一定有一个加到U里面维数会变大,因为U的意义实际上是长度<=某个数的串的集合,如果多了那么多的一定是更长的

    那么U一定是维数不断增加,之后到某个时刻不变,因为转移不变所以之后的U全部相等了

    又因为维数最多为n1+n2,所以假设存在坏串那一定可以在前n1+n2个U里找到(>n1+n2的和第n1+n2个相等)

    找到长度之后按位确定即可,计算时每次加到串首即可做到O(26nm)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%998244353
    #define mod 998244353
    #define ll long long
    //#define file
    using namespace std;
    
    ll rd[1001][26],sum;
    int i,j,k,l;
    char ch;
    struct G{
    	int n,m,a[3001][3],ls[501],len,i,j,k,l;
    	ll f[1001][501],g[501],G[501];
    	char ch;
    	
    	void New(int x,int y,int z) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;a[len][2]=z;}
    	void Read()
    	{
    		scanf("%d%d",&n,&m);
    		fo(i,1,m) scanf("%d%d%c%c",&j,&k,&ch,&ch),New(j,k,ch-'a');
    	}
    	void js(int t)
    	{
    		fo(i,1,n)
    		{
    			for (j=ls[i]; j; j=a[j][1])
    			add(f[t][i],f[t-1][a[j][0]]*rd[t][a[j][2]]);
    		}
    	}
    	void Js(int t,int c)
    	{
    		memset(G,0,sizeof(G));
    		fo(i,1,n)
    		{
    			for (j=ls[i]; j; j=a[j][1])
    			if (a[j][2]==c)
    			add(G[a[j][0]],g[i]);
    		}
    	}
    	void pd(int t,int s) {fo(i,1,n) add(sum,G[i]*f[t][i]*s);}
    	void change() {fo(i,1,n) g[i]=G[i];}
    } g1,g2;
    
    ll random(int x,int y) {return (1ll*rand()*23333+rand())%(y-x+1)+x;}
    
    int main()
    {
    	#ifdef file
    //	freopen("uoj552.in","r",stdin);
    	freopen("ex_string4.in","r",stdin);
    	#endif
    	
    	srand(time(NULL));
    	g1.Read(),g2.Read();
    	fo(i,1,g1.n+g2.n) fo(j,0,25) rd[i][j]=random(1,mod-1);
    	fo(i,1,g1.n) g1.f[0][i]=g1.g[i]=1;
    	fo(i,1,g2.n) g2.f[0][i]=g2.g[i]=1;
    	
    	fo(i,1,g1.n+g2.n)
    	{
    		g1.js(i),g2.js(i);
    		sum=0;
    		fo(j,1,g1.n) add(sum,g1.f[i][j]);
    		fo(j,1,g2.n) add(sum,-g2.f[i][j]);
    		
    		if (sum)
    		{
    			l=i;
    			fo(i,1,l)
    			{
    				fo(j,0,25)
    				{
    					sum=0;
    					g1.Js(i,j),g2.Js(i,j);
    					g1.pd(l-i,1),g2.pd(l-i,-1);
    					if (sum)
    					{
    						g1.change(),g2.change();
    						putchar(j+'a');
    						break;
    					}
    				}
    			}
    			return 0;
    		}
    	}
    	printf("Same
    ");
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
    [BZOJ3230] 相似字串 后缀数组+RMQ
    [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
    [BZOJ4044]Virus synthesis 回文自动机的DP
    [BZOJ2055]80人环游世界 有上下界最小费用最大流
    [BZOJ2502]清理雪道 有上下界网络流(最小流)
    [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)
    [BZOJ2288&BZOJ1150]一类堆+链表+贪心问题
    [BZOJ4820]硬币游戏 KMP+高斯消元
    [BZOJ1559]密码 AC自动机+状压
  • 原文地址:https://www.cnblogs.com/gmh77/p/13592129.html
Copyright © 2020-2023  润新知