HDU5509 : Pattern String
只要求出两个字符串的最小表示,然后就可以判断是否循环同构。
枚举最小表示的开头在哪个位置,然后求出Hash值,如果两个串的Hash值集合有交,那么说明循环同构。
因为串经过压缩,原串的长度很大,不能直接枚举开头。
考虑当开头在某个串$A^k$里某个位置时的性质:
假设$A^k$全在开头,现在考虑挪动一个$A$到结尾。
那么如果挪动之后字典序更小了,那么再挪动一个$A$到结尾,比较条件不变。
因此一旦挪动一个$A$之后字典序变小,那么最小表示一定是将$k-1$个$A$全部挪到结尾。
所以对于一个压缩串$A^k$,只需要在其第一次重复和最后一次重复的部分枚举开头即可。
对于这两部分,Hash值可以直接递推计算,对于中间$k-2$次移动,可以用矩阵快速幂计算。
时间复杂度$O(tk|S|\log|S|)$。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i) for(int i=0;i<2;i++)
using namespace std;
typedef long long ll;
typedef pair<int,int>PI;
const int N=30010,S=233,P[2]={1000000007,1000000009};
inline bool check(char x){return x>='a'&&x<='z';}
struct String{
char s[N];ll tot;
int cnt,n,len[N],w[N],st[N],en[N];
void read(){
static char a[N];
scanf("%s",a);
int l=strlen(a),i,j,k;
cnt=n=tot=0;
for(i=0;i<l;){
if(check(a[i])){
st[++n]=cnt+1;
for(j=i;j<l&&check(a[j]);j++);
for(k=i;k<j;k++)s[++cnt]=a[k];
en[n]=cnt;
len[n]=en[n]-st[n]+1;
w[n]=1;
tot+=len[n]*w[n];
i=j;
}else{
st[++n]=cnt+1;
for(j=++i;j<l&&check(a[j]);j++);
for(k=i;k<j;k++)s[++cnt]=a[k];
en[n]=cnt;
len[n]=en[n]-st[n]+1;
w[n]=0;
for(j++;j<l&&a[j]>='0'&&a[j]<='9';j++)w[n]=w[n]*10+a[j]-'0';
tot+=len[n]*w[n];
i=j;
}
}
}
void write(){
int i,j;
printf("%d %lld\n",n,tot);
for(i=1;i<=n;i++){
for(j=st[i];j<=en[i];j++)putchar(s[j]);
printf(" %d %d\n",len[i],w[i]);
}
}
}A,B;
namespace Hash{
char s[N];ll tot;
int cnt,n,i,j,k,x,y,len[N],w[N],st[N],en[N],f[N][2],g[2],mo;
struct mat{
int v[2][2];
mat(){}
mat operator*(const mat&b){
mat c;
rep(i)rep(j)c.v[i][j]=0;
rep(i)rep(j)rep(k)c.v[i][j]=(1LL*v[i][k]*b.v[k][j]+c.v[i][j])%mo;
return c;
}
};
inline int pow(int a,ll b,int P){int t=1;for(;b;b>>=1LL,a=1LL*a*a%P)if(b&1LL)t=1LL*t*a%P;return t;}
inline int cal(int f,int l,int w,int P){
mo=P;
mat A,B;
rep(i)rep(j)A.v[i][j]=B.v[i][j]=0;
B.v[1][0]=f;
A.v[0][0]=A.v[0][1]=1,A.v[1][1]=pow(S,l,P);
for(;w;w>>=1,A=A*A)if(w&1)B=A*B;
return B.v[0][0];
}
void solve(PI*v,int&cv,const String&p,ll L){
cv=cnt=n=0,tot=L;
for(i=1;i<=p.n;i++){
x=min(L/p.len[i],1LL*p.w[i]);
if(x){
st[++n]=cnt+1;
for(j=p.st[i];j<=p.en[i];j++)s[++cnt]=p.s[j];
en[n]=cnt;
len[n]=en[n]-st[n]+1;
w[n]=x;
}
L-=x*p.len[i];
if(!L)break;
if(L<p.len[i]&&x<p.w[i]){
st[++n]=cnt+1;
for(j=p.st[i];j<p.st[i]+L;j++)s[++cnt]=p.s[j];
en[n]=cnt;
len[n]=L;
w[n]=1;
break;
}
}
for(i=0;i<2;i++)g[i]=0;
for(i=1;i<=n;i++){
for(j=0;j<2;j++)f[i][j]=0;
for(j=st[i];j<=en[i];j++)for(k=0;k<2;k++)f[i][k]=(1LL*f[i][k]*S+s[j])%P[k];
for(j=0;j<2;j++)g[j]=(1LL*g[j]*pow(S,len[i]*w[i],P[j])+cal(f[i][j],len[i],w[i],P[j]))%P[j];
}
for(i=1;i<=n;i++){
for(j=st[i];j<=en[i];j++){
v[++cv]=PI(g[0],g[1]);
for(k=0;k<2;k++){
g[k]=(g[k]-1LL*s[j]*pow(S,tot-1,P[k])%P[k]+P[k])%P[k];
g[k]=(1LL*g[k]*S+s[j])%P[k];
}
}
if(w[i]==1)continue;
for(j=0;j<2;j++){
x=len[i]*(w[i]-2);
y=cal(f[i][j],len[i],w[i]-2,P[j]);
g[j]=(g[j]-1LL*y*pow(S,tot-x,P[j])%P[j]+P[j])%P[j];
g[j]=(1LL*g[j]*pow(S,x,P[j])+y)%P[j];
}
for(j=st[i];j<=en[i];j++){
v[++cv]=PI(g[0],g[1]);
for(k=0;k<2;k++){
g[k]=(g[k]-1LL*s[j]*pow(S,tot-1,P[k])%P[k]+P[k])%P[k];
g[k]=(1LL*g[k]*S+s[j])%P[k];
}
}
}
}
}
int T,C,k,o,ans,ca,cb,i,j;PI a[N],b[N];
int main(){
scanf("%d",&T);
for(C=1;C<=T;C++){
A.read();
scanf("%d",&k);ans=0;
for(o=1;o<=k;o++){
B.read();
Hash::solve(a,ca,A,B.tot);
Hash::solve(b,cb,B,B.tot);
sort(a+1,a+ca+1),sort(b+1,b+cb+1);
for(i=j=1;i<=ca&&j<=cb;){
if(a[i]<b[j])i++;
else if(a[i]>b[j])j++;
else{
ans+=o*o;
break;
}
}
}
printf("Case #%d: %d\n",C,ans);
}
return 0;
}
HDU5509 : Pattern String的更多相关文章
- (String). Word Pattern
Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...
- A Simple C++ Template Class that Matches a String to a Wildcard Pattern
A recently implemented enhanced wildcard string matcher, features of which including, Supporting wil ...
- java常用类与包装类--常用类正则表达式 String正则方法+Matcher+Pattern
0.java中的正则 java 中的正则总共涉及三个类(或者说1个String类和一个regex包) java.lang.String java.util. Matcher java.util.Pat ...
- int preg_match( string pattern
preg_match -- 进行正则表达式匹配.并且只匹配一次,注意与preg_match_all区别. int preg_match( string pattern, string subject ...
- [LeetCode] Word Pattern II 词语模式之二
Given a pattern and a string str, find if str follows the same pattern. Here follow means a full mat ...
- [LeetCode] Word Pattern 词语模式
Given a pattern and a string str, find if str follows the same pattern. Examples: pattern = "ab ...
- LeetCode 290 Word Pattern
Problem: Given a pattern and a string str, find if str follows the same pattern. Here follow means a ...
- leetcode(一)Word Pattern
题目描述: Given a pattern and a string str, find if str follows the same pattern. Here follow means a fu ...
- Lua 之string库
标准string库 基础字符串函数 string.len(s) 返回一个字符串的长度,例如 string.rep(s, n) 返回一个新的字符串,该字符串是参数s重复n次得到的结果,例如 )) -- ...
随机推荐
- 第四篇 基于.net搭建热插拔式web框架(RazorEngine实现)
在开头也是先给大家道个歉,由于最近准备婚事导致这篇文章耽误了许久,同时也谢谢老婆大人对我的支持. 回顾上篇文章,我们重造了一个controller,这个controller中用到了视图引擎,我们的视图 ...
- 异步控制---实现函数asyncAll,在执行完传入数组中func1,func2,func3异步函数后,输出“end”
实现函数asyncAll,在执行完传入数组中func1,func2,func3异步函数后,输出"end" function func1(callback) { setTimeout ...
- JavaFx客户端服务器C/S架构搭建
客户端获取服务器端软件更新版本方法: package com.platform.ui.update; import java.io.BufferedInputStream; import java.i ...
- 爬虫 htmlUnit遇到Cannot locate declared field class org.apache.http.impl.client.HttpClientBuilder.dnsResolve错误
当在使用htmlUnit时遇到无法定位org.apache.http.impl.client.HttpClientBuilder.dnsResolver类时,此时所需要的依赖包为: <depen ...
- Win10搭建Linux开发环境之网络连接设定
一直想在家自己搭建一个LINUX服务器,好在上面安装个ORACLE数据库玩玩. 上次用了Ubuntu,结果ORACLE没装成功,现在换个思路,采用CentOS 7作为Linux服务器, 之后再进行构建 ...
- c coroutine
今天看了下云风c coroutine 代码 博客,发现 coroutine 实现原理其实还比较简单,就用户态栈切换,只需要几十行汇编,特别轻量级. 具体实现 1. 创建一个coroutine: 也就 ...
- Git的用法
Git的用法 Git 的也可以理解为版本控制器.版本控制器(维基的解释):维护工程蓝图的标准作法,能追踪工程蓝图从诞生一直到定案的过程.此外,版本控制也是一种软件工程技巧,借此能在软件开发的过程中,确 ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
- Linux下GNOME桌面的安装
yum grouplist //列出yum仓库里的软件组列表 GNOME桌面的安装 yum install soft1 soft2 //使用yum源安装软件 yum groupinstall grou ...
- [转]Android静态变量的生命周期
原文地址:https://my.oschina.net/jerikc/blog/137207 Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的 ...