FZU problem 1985 LCP Problem
来源:互联网 发布:疯狂java讲义 豆瓣 编辑:程序博客网 时间:2024/05/28 05:15
给定n个字符串,询问任意两个字符串的最长公共前缀。每组数据最多100000个字符串,总长最多100000,询问最多100000。
解法一:hash+二分,二分最长公共前缀长度,用hash判定两个前缀是否一致。时间复杂度O(q*log(len))。/*-------------------FZU 1985 by Temle----------------*/#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <set>#include <map>#include <stack>#include <queue>#include <vector>#define ls(x) ((x)<<1)#define rs(x) ((x)<<1|1)using namespace std;typedef long long ll;typedef pair<ll,ll> pll;typedef pair<int,int> pii;#define mp(x,y) make_pair(x,y)#define fi first#define se second#define M 1000000007#define pri 233int hash1[201000],powh[201000];int getHash(int l,int r){ return hash1[r]-hash1[l-1]*powh[r-l+1];}char st[201000];int l[201000],r[201000];int main(){ powh[0]=1; for (int i=1;i<201000;i++) powh[i]=powh[i-1]*pri; int T,ca; for (scanf("%d",&T),ca=1;ca<=T;ca++) { int n; scanf("%d",&n); r[0]=0; for (int i=1;i<=n;i++) { l[i]=r[i-1]+2; scanf(" %s",st+l[i]); r[i]=l[i]+strlen(st+l[i])-1; hash1[l[i]-1]=0; for (int j=l[i];j<=r[i];j++) hash1[j]=hash1[j-1]*pri+st[j]; } int m; int x,y; scanf("%d",&m); printf("Case %d:\n",ca); for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); x++;y++; int ans=0,l1,r1,mid; l1=1; r1=min(r[x]-l[x],r[y]-l[y])+2; while (l1<r1) { mid=l1+r1>>1; if (getHash(l[x],l[x]+mid-1)==getHash(l[y],l[y]+mid-1)) { ans=mid; l1=mid+1; }else r1=mid; } printf("%d\n",ans); } } return 0;}
解法二:使用字典树存取每种字符串,并记录每种字符串对应的字典树中的叶子位置,查询任意两个字符串的最长公共前缀相当于在字典树上跑LCA。时间复杂度O(q*log(len))。/*-------------------FZU 1985 by Temle----------------*/#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <set>#include <map>#include <stack>#include <queue>#include <vector>#define ls(x) ((x)<<1)#define rs(x) ((x)<<1|1)using namespace std;typedef long long ll;typedef pair<ll,ll> pll;typedef pair<int,int> pii;#define mp(x,y) make_pair(x,y)#define fi first#define se second#define M 1000000007int loc[101000],dep[101000],fa[101000][20];int trans[128];struct Trie{int tot;struct node{int next[4];} a[101000];void reset(int id){ memset(a[id].next,0,sizeof(a[id].next));}void init(){memset(fa,0,sizeof(fa));tot=0;reset(0);}void insert(char *st,int id){int root=0;for (int i=0;st[i];i++){int y=trans[st[i]];if (a[root].next[y]==0) a[root].next[y]=++tot,reset(tot);root=a[root].next[y];}loc[id]=root;}void dfs(int x,int f){fa[x][0]=f;dep[x]=dep[f]+(x!=0);for (int i=0;i<4;i++) if (a[x].next[i]) dfs(a[x].next[i],x);}void build(){for (int j=1;j<20;j++) for (int i=1;i<=tot;i++) fa[i][j]=fa[fa[i][j-1]][j-1];}int lca(int u,int v){if (dep[u]<dep[v]) swap(u,v);int dx=dep[u]-dep[v],tmp=0;while (dx){if (dx&1) u=fa[u][tmp];tmp++;dx>>=1;}for (int i=19;i>-1;i--){if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];}return u==v?u:fa[u][0];}} trie;char str[101000];int main(){trans['A']=0;trans['G']=1;trans['C']=2;trans['T']=3;int T,ca;for (scanf("%d",&T),ca=1;ca<=T;ca++){trie.init();int n;scanf("%d",&n);for (int i=0;i<n;i++){scanf(" %s",str);trie.insert(str,i);}trie.dfs(0,0);trie.build();int m;scanf("%d",&m);printf("Case %d:\n",ca);for (int i=0;i<m;i++){int x,y;scanf("%d%d",&x,&y);printf("%d\n",dep[trie.lca(loc[x],loc[y])]);}} return 0;}
解法三:把所有字符串连接起来,中间用特殊字符分割,跑一遍后缀数组,然后只要计算任意两个后缀rank之间H数组的最小值即为答案。时间复杂度O(q*log(len))。/*-------------------FZU 1985 by Temle----------------*/#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <set>#include <map>#include <stack>#include <queue>#include <vector>#define ls(x) ((x)<<1)#define rs(x) ((x)<<1|1)using namespace std;typedef long long ll;typedef pair<ll,ll> pll;typedef pair<int,int> pii;#define mp(x,y) make_pair(x,y)#define fi first#define se second#define M 1000000007const int N=201000;int n,rank[N],sa[N],height[N],tmp[N],cnt[N];int s[N];void suffixarray(int n,int m){ int i,j,k; n++; for(i=0; i<n*2+5; i++)rank[i]=sa[i]=height[i]=tmp[i]=0; for(i=0; i<m; i++)cnt[i]=0; for(i=0; i<n; i++)cnt[rank[i]=s[i]]++; for(i=1; i<m; i++)cnt[i]+=cnt[i-1]; for(i=0; i<n; i++)sa[--cnt[rank[i]]]=i; for(k=1; k<=n; k<<=1) { for(i=0; i<n; i++) { j=sa[i]-k; if(j<0)j+=n; tmp[cnt[rank[j]]++]=j; } sa[tmp[cnt[0]=0]]=j=0; for(i=1; i<n; i++) { if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i; sa[tmp[i]]=j; } memcpy(rank,sa,n*sizeof(int)); memcpy(sa,tmp,n*sizeof(int)); if(j>=n-1)break; } for(j=rank[height[i=k=0]=0]; i<n-1; i++,k++) while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rank[sa[j]+1];}void get_height(int s[], int n){ int i, j, k; for(i = 0; i < n; ++ i) rank[sa[i]] = i; for(j = i = 0; i < n; ++ i) { if(rank[i] == 0) height[0] = j = 0; else { for(k = sa[rank[i] - 1], j = max(j - 1, 0); s[i+j] && s[i+j] == s[k+j]; ++ j); height[rank[i]] = j; } }}const int RMQ_N = 7 + 201000;int Log2[RMQ_N],Pow2[30];struct RMQ{ int st[RMQ_N][30],n,m; int cmp(int a,int b) { return a<b ? a : b; } void init(int dig[],int n) { this->n=n; Log2[1]=0; for (int i=2; i<=n; i++) Log2[i]=Log2[i>>1]+1; m=Log2[n]; Pow2[0]=1; for (int i=1; i<30; i++) Pow2[i]=Pow2[i-1]<<1; for (int i=1; i<=n; i++) st[i][0]=dig[i]; for (int j=1; j<=m; j++) for (int i=1; i+Pow2[j]-1<=n; i++) st[i][j]=cmp(st[i][j-1],st[i+Pow2[j-1]][j-1]); } int query(int l,int r) { if (l>r) swap(l,r); int tmp = Log2[r-l+1]; return cmp(st[l][tmp],st[r-Pow2[tmp]+1][tmp]); }} rmq;int l[201000],r[201000],len[201000];char st[N];int main(){ int T,ca; for (scanf("%d",&T),ca=1; ca<=T; ca++) { int n; scanf("%d",&n); r[0]=-1; int mod=121; for (int i=1; i<=n; i++) { l[i]=r[i-1]+1; scanf(" %s",st+l[i]); r[i]=l[i]+strlen(st+l[i])-1; for (int j=l[i]; j<=r[i]; j++) s[j]=st[j]; len[i]=r[i]-l[i]+1; r[i]++; mod++; s[r[i]]=mod; } suffixarray(r[n],10300); get_height(s,r[n]); rmq.init(height,r[n]); int m; scanf("%d",&m); printf("Case %d:\n",ca); for (int i=1; i<=m; i++) { int x,y; scanf("%d%d",&x,&y); x++; y++; int a=rank[l[x]]; int b=rank[l[y]]; if (a>b) swap(a,b); int ans; if (a==b) ans=len[x]; else ans=rmq.query(a+1,b); printf("%d\n",ans); } } return 0;}
0 0
- FZU problem 1985 LCP Problem
- FZU Problem 1985 LCP Problem (字符串深度分析)
- FZU Problem 2104 Floor problem
- fzu problem 1013 rpgame
- FZU Problem 2110 Star
- FZU Problem 2054 拳王
- FZU 1692 Key problem
- FZU 2104 Floor problem
- FZU 2108 MOD problem
- fzu Problem 2154 YesOrNo
- fzu Problem 2152 文件系统
- FZU Problem 2169 shadow
- FZU A-B problem
- FZU Problem 2169 shadow
- FZU Problem 2082 过路费
- fzu Problem 2127 养鸡场
- FZU - 2104 Floor problem
- FZU 2214 Knapsack problem
- 查询mysql是否锁表,表是否在使用
- SpringBoot运行原理
- AngularJS $http 异步后台无法获取请求参数
- Linux I/O复用:select ,poll,epoll
- 浅谈JavaScript的组成——ECMAScript、BOM和DOM
- FZU problem 1985 LCP Problem
- 导频优先级是做什么的?
- linux syslog详解
- 深度解析SpringMvc实现原理手写SpringMvc框架
- CSS 基础(009_Max-width)
- IBM 全新大数据分析平台,助力数据云化
- WIN10配置环境变量
- 关于在Androidstudio的Message中报mergeDebugResources...finished with non-zero exit value 42错误的问题
- 一致性哈希算法(用于解决服务器均衡问题)