hdoj 4644 BWT 字符串匹配
来源:互联网 发布:上海科创板交易软件 编辑:程序博客网 时间:2024/04/30 15:31
昨天比赛和强神讨论了快一个小时,也得出了题解上的方法,只是不知道该怎么实现,按照我们两个想的,要求出原串的时间复杂度是o(n^2*logn),而且空间也很大,没办法写,然后今天看了大牛的标程,发现分析还是差了那么一点。
大牛的解析:
可以注意到生成的BWT(T)可以还原成为原始的T,方法如下表所示
ADD 1
g
c
$
a
a
a
c
SORT 1
$
a
a
a
c
c
g
ADD 2
g$
ca
$a
aa
ac
ac
cg
SORT 2
$a
aa
ac
ac
ca
cg
g$
ADD 3
g$a
caa
$ac
aac
aca
acg
cg$
SORT 3
$ac
aac
aca
acg
caa
cg$
g$a
ADD 4
g$ac
caac
$aca
aacg
acaa
acg$
cg$a
SORT 4
$aca
aacg
acaa
acg$
caac
cg$a
g$ac
ADD 5
g$aca
caacg
$acaa
aacg$
acaac
acg$a
cg$ac
SORT 5
$acaa
aacg$
acaac
acg$a
caacg
cg$ac
g$aca
ADD 6
g$acaa
caacg$
$acaac
aacg$a
acaacg
acg$ac
cg$aca
SORT 6
$acaac
aacg$a
acaacg
acg$ac
caacg$
cg$aca
g$acaa
ADD 7
g$acaac
caacg$a
$acaacg
aacg$ac
acaacg$
acg$aca
cg$acaa
SORT 7
$acaacg
aacg$ac
acaacg$
acg$aca
caacg$a
cg$acaa
g$acaac
然后就是怎么写可以将原串求出来,不用最笨的方法。
注意分析就会发现,每次对新增加字符的字符串进行排序时,其排序的位置都是相同的,即例子中的原串为gc$aaac,第一次按照升序排列好为$aaaccg,将两个串合并后的到的所有的字符串就是
g$ 排完序后为 $a
ca aa
$a ac
aa ac
ac ca
ac cg
cg g$
接下来利用kmp算法依次来匹配下面的询问就可以了。(我是多久没有写过kmp啦,竟然把next数组建立在了主串上,贡献了好多的TLE O_O );
下面的代码是看了标程之后写的,不懂可以看注释!
/////////////////////////////////////////////////////////////////////////// File Name: 4644.cpp// Author: wang// mail: // Created Time: 2013-8-7 10:39:29/////////////////////////////////////////////////////////////////////////#include <cstdio>#include <cstdlib>#include <climits>#include <cstring>#include <cmath>#include<string>#include <algorithm>#include<iostream>#include<queue>#include <map>using namespace std;typedef long long ll;#define INF (INT_MAX/10)#define SQR(x) ((x)*(x))#define rep(i, n) for (int i=0; i<(n); ++i)#define repf(i, a, b) for (int i=(a); i<=(b); ++i)#define repd(i, a, b) for (int i=(a); i>=(b); --i)#define clr(ar,val) memset(ar, val, sizeof(ar))#define pb(x) push_back(x)#define N 100096int n;int next[N];char a[200010];string s;string solve(){string but=s;vector<int>cont(s.length(),0);//记录最后一行的字符前面字符的个数的 vector<int>pos[30];//用来记录给定的字符串中第i个字符其前面与它相同的字符的个数的rep(i,but.size()) if(but[i]!='$') { cont[i]=pos[but[i]-'a'].size();//前面相同字符的个数的 pos[but[i]-'a'].pb(i); }//对给定的字符进行排序,来保证最先的字典序的string sorted=s;sort(sorted.begin(),sorted.end());//cout<<sorted<<endl;//排序后第i出现的某个字符所在的位置的,即指向添加后再排序所在的位置的rep(i,26) pos[i].clear();repf(i,1,sorted.length()-1) pos[sorted[i]-'a'].pb(i);//进行操作的核心string dis;char ch=s[0];//结尾的第一个字符的int place=0;//结尾的第一个字符排序后所在相同字符的位置的,因为后面为'$',所以肯定是第一个的rep(i,s.length()-1){dis+=ch;//该字符添加后排序所对应的位置的 int pp=pos[ch-'a'][place];//其后前面再次添加的字符即为原串所对应的字符 ch=s[pp];//获得新前面的字符place=cont[pp];//新获得的字符排序后所在相同字符中的位置的}reverse(dis.begin(),dis.end());return dis;}void kmp(string dis){memset(next,-1,sizeof(next));int j=-1;rep(i,dis.length()){while(j!=-1 && dis[i]!=dis[j]) j=next[j]; next[i+1]=++j;}next[0]=0;}int main(){while(cin>>s){ string p=solve();int q;scanf("%d",&q);while(q--){scanf("%s",a);int len=strlen(a); string pp=a; kmp(pp); int j=0;int flag=0;rep(i,p.length())//匹配{ while(a[j]!=p[i] && j!=0) j=next[j];if(a[j]==p[i]) ++j;if(j==len){flag=1; break;}}if(flag==1) printf("YES\n");else printf("NO\n");}}}
- hdoj 4644 BWT 字符串匹配
- hdu 4644 BWT (kmp)
- bwt
- bwt
- hdu4644 BWT
- BWT算法
- 最大匹配-HDOJ 1068
- HDOJ 1068 二分匹配
- HDOJ 1083 二分匹配
- HDOJ 1151 二分匹配
- 【二分匹配】 HDOJ 3118
- hdoj Human Gene Functions 1080 (DP) 字符串匹配求最大和
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- rman show all小记
- 利用json数据做父子二级菜单
- 【原创】编写Oracle存储过程解析XML,并把数据持久化
- UVALive 4394 String painter
- 解决windows传送到linux下中文文件名及文件内容乱码问题
- hdoj 4644 BWT 字符串匹配
- 解决firefox不支持innerText的办法
- uboot main_loop分析
- oracle PlSQL连接配置文件
- Windows批处理切换IP地址使用方法
- 类型参数约束 : Controller where T : class,new()
- synchronized与static synchronized 的区别
- 在IIS下面创建网站浏览提示要输入用户名和密码
- Ural 1282. Game Tree