51nod 1753 相似子串
来源:互联网 发布:通利琴行淘宝店铺 编辑:程序博客网 时间:2024/06/07 21:57
51nod 1753 相似子串
原题链接:
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1753
很少写字符串hash的题目。这算是第一个啦
对字符单独考虑。
考虑字符串的hash
定义A[k][i] :
A[k][i]=[s[i]=k]
对于一个01 串s ,定义它的hash 值为:
h(s)=∑i=1|s|s[i]bi mod P,P为素数
为了避免冲突。多次hash
那么对于等价的字符形成的01 串的hash 值是可以直接相加的
因为一个字符只可能属于一个A[k][] 。
hash 值其实是一个b 进制数.所以不会出现某一位数字超过1
那么如果有s1 ,s2 有一位不同时:hash(s1)−hash(s2)=Pk
直接查询即可。
#include <algorithm>#include <string.h>#include <stdio.h>#include <cmath>#define MAXN 300005using namespace std;typedef long long LL;const char ll='0'-1;const char rr='9'+1;struct Io{ char A[MAXN]; char *Pb=A,*Pe=A; void Io_fread() { Pb=A; Pe=A+fread(A,1,MAXN,stdin); } void s_read(char *s) { if(Pb==Pe)Io_fread(); if(Pb==Pe)return ; while(*Pb=='\n'||*Pb=='\r'||*Pb==' ') { Pb++; if(Pb==Pe) { Io_fread(); if(Pb==Pe)return ; } } while(*Pb!='\n'&&*Pb!='\r') { *s=*Pb; s++; Pb++; if(Pb==Pe) { Io_fread(); if(Pb==Pe) { *s=0; return; } } } *s=0; } char c_read()//读取一个字符 不读 空格换行 { if(Pb==Pe)Io_fread(); if(Pb==Pe)return -1; while(*Pb=='\n'||*Pb=='\r'||*Pb==' ') { Pb++; if(Pb==Pe) { Io_fread(); if(Pb==Pe)return -1; } } return *(Pb++); } int read() { int tmp=0; if(Pb==Pe)Io_fread(); if(Pb==Pe)return -1; while(*Pb=='\n'||*Pb=='\r'||*Pb==' ') { Pb++; if(Pb==Pe) { Io_fread(); if(Pb==Pe)return -1; } } while(*Pb>ll&&*Pb<rr) { tmp=tmp*10+(*Pb-'0'); Pb++; if(Pb==Pe) { Io_fread(); if(Pe==Pb)return tmp; } } return tmp; }}I;const int P1=998244353;const int P2=985661441;const int P3=1e8+7;const LL base=1e9+7;struct HasH{ int k1,k2,k3; HasH(int k1,int k2,int k3):k1(k1),k2(k2),k3(k3){} HasH() { k1=k2=k3=0; } bool operator ==(const HasH&a)const { return k1==a.k1&&k2==a.k2&&k3==a.k3; } HasH operator +(const HasH &a)const { return HasH((k1+a.k1)%P1,(k2+a.k2)%P2,(k3+a.k3)%P3); } HasH operator -(const HasH &a)const { return HasH((k1-a.k1+P1)%P1,(k2-a.k2+P2)%P2,(k3-a.k3+P3)%P3); }}H[26][MAXN];struct node{ int k,d; node(int k,int d):k(k),d(d){}; node() { *this=node(0,-1); } bool operator <(const node &a)const { if(k!=a.k)return k<a.k; return d<a.d; } bool operator ==(const node &a)const { return d==a.d; }}B[3][MAXN];int Pow(int a,int b,int mod){ LL tmp=1; while(b) { if(b&1) tmp=tmp*a%mod; a=(LL)a*a%mod; b>>=1; } return (int)tmp;}int Iv[3][MAXN];int po[3][MAXN];void init(){ po[0][0]=po[1][0]=po[2][0]=1; for(int i=0;i<MAXN;i++) { B[0][i]=node(po[0][i],i); B[1][i]=node(po[1][i],i); B[2][i]=node(po[2][i],i); Iv[0][i]=Pow(po[0][i],P1-2,P1); Iv[1][i]=Pow(po[1][i],P2-2,P2); Iv[2][i]=Pow(po[2][i],P3-2,P3); if(i+1<MAXN)po[0][i+1]=base*po[0][i]%P1; if(i+1<MAXN)po[1][i+1]=base*po[1][i]%P2; if(i+1<MAXN)po[2][i+1]=base*po[2][i]%P3; } sort(B[0],B[0]+MAXN); sort(B[1],B[1]+MAXN); sort(B[2],B[2]+MAXN);}struct Bf{ int A[26]; void clear() { for(int i=0;i<26;i++)A[i]=i; } Bf() { clear(); } int find(int a) { if(a==A[a])return a; return A[a]=find(A[a]); } void merg(int a,int b) { a=find(a); b=find(b); A[a]=b; }}F;char s[MAXN];bool vis[26];HasH used[2][26];int camp(int b){ int k1=(P1+used[0][b].k1-used[1][b].k1)%P1; int k2=(P2+used[0][b].k2-used[1][b].k2)%P2; int k3=(P3+used[0][b].k3-used[1][b].k3)%P3; int d1=(int)(lower_bound(B[0],B[0]+MAXN,node(k1,-1))-B[0]); if(d1<MAXN&&B[0][d1].k==k1) { for(int j=d1;j<MAXN&&B[0][j].k==B[0][d1].k;j++) { int d=(int)(lower_bound(B[1],B[1]+MAXN,node(k2,B[0][j].d))-B[1]); if(d>=MAXN||B[1][d].k!=k2||!(B[0][j]==B[1][d]))continue; d=(int)(lower_bound(B[2],B[2]+MAXN,node(k3,B[0][j].d))-B[2]); if(d>=MAXN||B[2][d].k!=k3||!(B[0][j]==B[2][d]))continue; return 1; } } k1=(P1-k1)%P1; k2=(P2-k2)%P2; k3=(P3-k3)%P3; d1=(int)(lower_bound(B[0],B[0]+MAXN,node(k1,-1))-B[0]); if(d1<MAXN&&B[0][d1].k==k1) { for(int j=d1;j<MAXN&&B[0][j].k==B[0][d1].k;j++) { int d=(int)(lower_bound(B[1],B[1]+MAXN,node(k2,B[0][j].d))-B[1]); if(d>=MAXN||B[1][d].k!=k2||!(B[0][j]==B[1][d]))continue; d=(int)(lower_bound(B[2],B[2]+MAXN,node(k3,B[0][j].d))-B[2]); if(d>=MAXN||B[2][d].k!=k3||!(B[0][j]==B[2][d]))continue; return 1; } } return 3;}int main (){ init(); I.s_read(s+1); for(int i=0;i<26;i++) { for(int j=1;s[j];j++) { if(s[j]-'a'==i) H[i][j]=HasH(po[0][j],po[1][j],po[2][j]); H[i][j]=H[i][j-1]+H[i][j]; } } int t,k,l1,l2,r1,r2; char a,b; t=I.read(); while(t--) { F.clear(); memset(vis,0,sizeof vis); for(int i=0;i<26;i++)used[0][i]=used[1][i]=HasH(0,0,0); k=I.read(); l1=I.read(); r1=I.read(); l2=I.read(); r2=I.read(); for(int i=0;i<k;i++) { a=I.c_read(); b=I.c_read(); F.merg(a-'a',b-'a'); } if(r1-l1!=r2-l2) { printf("NO\n"); continue; } for(int i=0;i<26;i++) { int u=F.find(i); used[0][u]=used[0][u]+H[i][r1]-H[i][l1-1]; used[1][u]=used[1][u]+H[i][r2]-H[i][l2-1]; } int flag=0; for(int u=0;u<26;u++) { int i=F.find(u); if(vis[i])continue; vis[i]=true; LL I1=Iv[0][l1-1]; LL I2=Iv[1][l1-1]; LL I3=Iv[2][l1-1]; used[0][i].k1=I1*used[0][i].k1%P1; used[0][i].k2=I2*used[0][i].k2%P2; used[0][i].k3=I3*used[0][i].k3%P3; I1=Iv[0][l2-1]; I2=Iv[1][l2-1]; I3=Iv[2][l2-1]; used[1][i].k1=I1*used[1][i].k1%P1; used[1][i].k2=I2*used[1][i].k2%P2; used[1][i].k3=I3*used[1][i].k3%P3; if(used[0][i]==used[1][i])continue; flag+=camp(i); if(flag>2)break; } if(flag<3) printf("YES\n"); else printf("NO\n"); }}
阅读全文
1 0
- 51nod 1753 相似子串
- 51Nod-1753-相似子串
- 【51Nod1753】相似子串
- 相似子串 bzoj3230
- BZOJ3230 相似子串
- [51nod 1304]字符串的相似度
- 51Nod 1304 字符串的相似度
- 51nod 1088 最长回文子串
- 51nod 1088 最长回文子串
- 51nod 1088 最长回文子串
- 51nod-【1088 最长回文子串】
- 51nod 1088 最长回文子串
- 【51nod】1088 最长回文子串
- 51nod 1081子串求和
- 51nod 1469 淋漓尽致子串
- 51Nod 1088 最长回文子串
- 51Nod-1469-淋漓尽致子串
- 51Nod-1088-最长回文子串
- Unity3D-塔防游戏项目主要源码(游戏主控器脚本)
- 对一阶二阶低通数字滤波器的理解(基于匿名微型六轴)
- GDI+的使用
- 样本方差的无偏估计与(n-1)的由来
- 聊聊流水线处理器
- 51nod 1753 相似子串
- Unity3D-塔防游戏项目主要源码(游戏UI界面控制器脚本)
- FSM
- [Azure]使用Powershell删除ARM模式下单台虚拟机及相关资源(非托管磁盘)
- java Web.xml的配置
- 【LeetCode】55、jump game
- 单例模式(Singleton)应用场景和优缺点
- HDU 3986 Harry Potter and the Final Battle 删掉任意一条边的最长最短路(有重边)
- 51NOD 1210 矩阵查询 【线段树/树状数组】