• [51nod 1753] 相似子串


    问题描述

    两个字符串相似定义为:
    1.两个字符串长度相等
    2.两个字符串对应位置上有且仅有至多一个位置所对应的字符不相同
    给定一个字符串,每次询问两个子串在给定的规则下是否相似。给定的规则指每次给出一些等价关系,如‘a'=’b',‘b'=’c'等,注意这里的等价关系具有传递性,即若‘a'=’b',‘b'=’c',则‘a'=’c'。

    输入格式

    第一行一个字符串s(1<=|s|<=300000)
    第二行一个整数T(1<=T<=300000)
    对于每次询问:
    第一行5个整数k,l1,r1,l2,r2,表示有k个等价规则,询问的是子串[l1,r1],l2,r2
    接下来k行每行两个连续的字符表示这两个字符等价。
    此题中所有的字符均为小写字母。

    输出格式

    T行,若相似则输出“YES”否则输出“NO”

    样例输入

    abac
    3
    1 1 2 3 4
    bc
    1 1 2 3 4
    ac
    1 1 2 2 3
    ac

    样例输出

    YES
    YES
    NO

    解析

    如果想要得到两个字符串是否相似,也就是说允许有一个字符不一样,那么不妨分为左边和右边两部分分别比较。如果两边完全一样,自然原来的两个字符串也是相似的;如果两边都不一样,那么不可能做到只有一个字符不一样,也就是说两个字符串不相似。当只有一边是一样的时候,就去验证不一样的那一半,这就是一个子问题了。

    接下来的问题是如何比较两个字符串是否相等。可以用哈希来解决。由于会出现相同规则的更改,用并查集维护相同字母的关系,然后分字母进行哈希,最后计算时在合并即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define int long long
    #define N 300002
    using namespace std;
    const int p=199999;
    const int mod=1000000007;
    int t,l,i,j,fa[30],k,l1,r1,l2,r2,hash[N][30],poww[N];
    char s[N];
    int id(char x)
    {
    	return (int)(x-'a'+1);
    }
    int find(int x)
    {
    	if(x!=fa[x]) fa[x]=find(fa[x]);
    	return fa[x];
    }
    int Hash(int l,int r)
    {
    	int ans=0;
    	for(int i=1;i<=26;i++){
    		int tmp=(hash[r][i]-hash[l-1][i]*poww[r-l+1]%mod+mod)%mod;
    		ans=(ans+tmp*(find(i)+1)%mod)%mod;
    	}
    	return ans;
    }
    signed main()
    {
    	cin>>s>>t;
    	l=strlen(s);
    	poww[0]=1;
    	for(i=1;i<=l;i++) poww[i]=poww[i-1]*p%mod;
    	for(i=1;i<=l;i++){
    		for(j=1;j<=26;j++) hash[i][j]=hash[i-1][j]*p%mod;
    		hash[i][id(s[i-1])]=(hash[i][id(s[i-1])]+1)%mod;
    	}
    	while(t--){
    		cin>>k>>l1>>r1>>l2>>r2;
    		for(i=1;i<=26;i++) fa[i]=i;
    		for(i=1;i<=k;i++){
    			char a,b;
    			cin>>a>>b;
    			if(find(id(a))!=find(id(b))) fa[find(id(a))]=find(id(b));
    		}
    		bool flag=1;
    		while(l1<r1&&l2<r2){
    			int mid1=(l1+r1)/2,mid2=(l2+r2)/2;
    			int h1=Hash(l1,mid1),h2=Hash(mid1+1,r1),h3=Hash(l2,mid2),h4=Hash(mid2+1,r2);
    			if(h1!=h3&&h2!=h4){
    				flag=0;
    				break;
    			}
    			else if(h1==h3&&h2==h4) break;
    			else if(h1==h3) l1=mid1+1,l2=mid2+1;
    			else r1=mid1,r2=mid2;
    		}
    		if(flag) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Find cmd
    splitFile2SmallFile
    IPC-->PIPO
    Thread and shared lock
    Python Thread related
    linux 文件系统
    linux commands
    关于 gnome3 无法显示应用程序所有界面的反馈
    Windows 网络编程
    常见端口 HTTP代码
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11872986.html
Copyright © 2020-2023  润新知