CF 119D String Transformation(KMP,雜湊,列舉,各種優化)
轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
題目:有兩個串,s,f f(s, i, j) = s[i + 1... j - 1] + r(s[j... n - 1]) + r(s[0... i]).
通過二元組(i,j)對原串s進行變換,得到新的串,現在要你求這個二元組
http://codeforces.com/problemset/problem/119/D
哈哈,爽,終於A了
第一次在CF上除錯這麼艱辛,TLE+WA刷了好多
我們將兩個串表示成a,b,分為三個部分
a ( 1 , 2 , 3 ) a'表示a的反序
那麼b ( 2 , 3' , 1' ) b'表示b的反序
我的做法是,第一步,列舉i,首先我們可以看到a和b‘的最長公共字首。
由於 題目要求i最大,所以先求出a和b'的最長公共字首長度,mx+1
然後i便可以從mx可能列舉。
接下來相當於列舉j,但是直接列舉肯定會TLE
可以發現b的字尾除了1'之後,便是a’的字首。
那麼我們用a'和b做一次KMP,記錄對於b中的某個位置,能匹配的最遠距離pos[]
但是並不一定j越遠就好,所以列舉的時候,從pos[]出發,通過next[]陣列就能列舉到可能的j
這樣列舉出來的,肯定是滿足1,3這兩個部分
剩下的就是判斷兩個串的剩下部分也就是部分2是否匹配了。這一部分通過HASH就能O(1)處理。
但是這樣還是會TLE,因為可以知道像aaaaaaaaaaabaaaaaaaaa這種串,通過next陣列轉移很慢的。還是相當於列舉
這裡我又加了個優化,用b串和a串直接跑一次KMP,記錄對於a中的某個位置,和b的字首最長能匹配的長度dp[]。
那麼在列舉i之後,列舉j,通過這個長度 能作一次剪枝
但是這裡又WA了很久。這是因為在處理dp[]陣列的時候,我只是在向前移動匹配的時候,轉移了dp[]陣列,其實是不對的。即使不能匹配,通過next[]陣列,也是能得到字尾的字首和字首是匹配的,也是可以轉移的。
以上想法,純屬是自己不成熟的做法,而且也表述不清
歡迎交流。可以看下程式碼
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1600005
#define M 40
#define N 1000005
#define maxn 300005
#define eps 1e-12
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
#define test puts("OK");
#define pi acos(-1.0)
#define lowbit(x) ((-(x))&(x))
#define HASH1 1331
#define HASH2 10001
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
char a[N],a_2[N],b[N];
int la,lb;
int next[N];
int pos[N];
int dp[N];
LL fac1[N]={1},fac2[N]={1};
LL h11[N]={0},h21[N]={0};
LL h12[N]={0},h22[N]={0};
void get_next(char *s,int len){
next[0]=-1;
int i=0,j=-1;
while(i<len){
if(j==-1||s[i]==s[j]){
i++;j++;
next[i]=j;
}
else j=next[j];
}
}
void match(char *pat,int lp,char *str,int ls,int flag){
int i=0,j=0;
while(i<lp&&j<ls){
if(i==-1||pat[i]==str[j]){
if(!flag) pos[j]=i;
if(flag&&i!=-1){
dp[j-i]=max(dp[j-i],i+1);
}
i++;j++;
}
else{
i=next[i];
dp[j-i]=max(dp[j-i],i+1);
}
if(i==lp) i=next[i];
}
}
LL get(int l,int r,LL *hash,LL *fac){
l++;r++;
return hash[r]-hash[l-1]*fac[r-l+1];
}
int main(){
//freopen("input.txt","r",stdin);
for(int i=1;i<N;i++){
fac1[i]=fac1[i-1]*HASH1;
fac2[i]=fac2[i-1]*HASH2;
}
while(gets(a)!=NULL&&gets(b)!=NULL){
la=strlen(a);lb=strlen(b);
if(la!=lb){
//if(a[0]==a[1]&&a[2]==a[3]&&a[2]==' ') cout<<3333333333<<endl;
printf("-1 -1\n");
continue;
}
for(int i=0;i<la;i++)
a_2[i]=a[la-i-1];
for(int i=1;i<=la;i++){
h11[i]=h11[i-1]*HASH1+a[i-1];
h12[i]=h12[i-1]*HASH2+a[i-1];
}
for(int i=1;i<=lb;i++){
h21[i]=h21[i-1]*HASH1+b[i-1];
h22[i]=h22[i-1]*HASH2+b[i-1];
}
get_next(a_2,la);
match(a_2,la,b,lb,0);
mem(dp,-1);
get_next(b,lb);
match(b,lb,a,la,1);
int l=-1,r=-1,mx=-1;
for(int i=0;i<la;i++)
if(a[i]==b[lb-i-1]){
mx=i;
}
else break;
for(int i=min(la-2,mx);i>=0;i--){
int p=pos[lb-i-2];
while(p>=0){
int j=la-p-1;
if(j-i-1>dp[i+1]&&j-i-1!=0) break;
if(i+1==j){
l=i,r=j;
}
else{
LL t1=get(i+1,j-1,h11,fac1),t2=get(0,j-i-2,h21,fac1);
LL t3=get(i+1,j-1,h12,fac2),t4=get(0,j-i-2,h22,fac2);
if(t1==t2&&t3==t4) l=i,r=j;
}
p=next[p];
if(l!=-1) break;
}
if(l!=-1) break;
}
printf("%d %d\n",l,r);
}
return 0;
}
相關文章
- golang 效能優化之累加雜湊Golang優化
- 如何優化一個雜湊策略優化
- JAVA單例模式的各種寫法分析,最優為列舉Java單例模式
- PLC結構化文字(ST)——列舉_to_string(to_string)
- CF985F Isomorphic Strings (雜湊)
- UOJ Round #15 [構造 | 計數 | 異或雜湊 kmp]KMP
- 通過雜湊聯接進行高階優化優化
- SQL優化--用各種hints優化一條SQLSQL優化
- N皇后問題(各種優化)優化
- 雜湊表的兩種實現
- 為什麼Java String雜湊乘數為31?Java
- (dp+雜湊)CF1624E Masha-forgetful
- CF580E Kefa and Watch (線段樹維護雜湊)
- js 雜湊雜湊值的模組JS
- 雜湊表(雜湊表)詳解
- PHP 陣列的雜湊碰撞攻擊PHP陣列
- 雜湊
- 優雅使用前端列舉Enum,符合國標的那種!前端
- 從雜湊表(HashTable)的角度深入理解《PHP 陣列的雜湊碰撞攻擊》PHP陣列
- 一站式解決使用列舉的各種痛點
- 雜湊表(雜湊表)原理詳解
- 【尋跡#3】 雜湊與雜湊表
- SerializationFeature各列舉項的作用
- 第23章:列表、陣列和雜湊表陣列
- 查詢(3)--雜湊表(雜湊查詢)
- POJ 3080 Blue Jeans (KMP+暴力列舉)【模板】KMP
- 樹雜湊
- 雜湊碰撞
- 字串雜湊字串
- 雜湊表
- MapperFeature各列舉項的作用APP
- Oracle優化器:星型轉換(Star Query Transformation )Oracle優化ORM
- 從一條問題SQL優化看SQL TransformationSQL優化ORM
- 行轉列的一種優化思路優化
- 資料結構基礎 (程式碼效率優化, 線性表, 棧, 佇列, 陣列,字串,樹和二叉樹,雜湊表)資料結構優化佇列陣列字串二叉樹
- 雜湊函式函式
- 字串雜湊表字串
- redis之雜湊Redis