トピック:
http://poj.org/problem?id=2774
- ロングロングメッセージ
小さな猫はByterlandの首都で物理学を専攻しています。悲しいニュースの一部は、これらの日に彼に来る:彼の母親が病気になっています。(Byterlandは、このような大きな国であり、そして彼は彼の故郷へ電車で16 shoursを費やす必要があります)鉄道の切符にはあまりを費やして心配なので、彼は彼の母親とSMSを送信することを決定しました。
小さな猫はunrich家族に住んでいるので、彼は頻繁に彼がSMSで過ごしたどのくらいのお金を確認するには、携帯電話サービスセンターに来ます。昨日、サービスセンターのコンピュータが壊れていた、と2つの非常に長いメッセージを印刷しました。華麗な小さな猫はすぐに見つけた:
1.メッセージのすべての文字が句読点やスペースを入れずに、小文字のラテン文字です。
2.すべてのSMSが相互に追加されました-これら2件のメッセージがかなり長くている理由である- (I + 1)番目のSMSは、i番目の1の直後に来ます。
3.彼自身のSMSが一緒に追加されているが、おそらく非常に多くの冗長文字が原因壊れたコンピュータに左右に表示されます。
例:彼のSMSは「motheriloveyou」、のいずれか、そのマシンで印刷された長いメッセージであれば、おそらく「hahamotheriloveyou」、「motheriloveyoureally」、「motheriloveyouornot」、「bbbmotheriloveyouaaa」の1などとなり
、これらの壊れた問題については4、少し猫は二回、彼の元のテキストを印刷した(ので、2件の非常に長いメッセージが表示されます)。オリジナルのテキストは2つのプリントのメッセージに同じままであっても、両側に冗長文字はおそらく異なるだろう。
あなたはこれらの2つの非常に長いメッセージを与えている、とあなたは出力に小さな猫によって書かれた最長の可能元のテキストの長さを持っています。
背景:
ByterlandモバイルサービスでのSMSはドルあたりのバイトに充電されています。小さな猫が最長のオリジナルテキストは可能性がどのくらいの心配をされている理由です。
なぜプログラムを書くように頼みますか?4 resionsがあります。
小さな猫1.物理学の授業で、これらの日忙しいです。
2.小さな猫は、彼が彼の母親のseceretに言っておきたいです。
3. POJは、このような偉大なオンライン裁判官です。
4.小さな猫がPOJからいくつかのお金を稼ぐ、と医者に彼の母親を説得しようとしたい:(
入力
個別入力ラインの2に小文字を持つ2つの文字列。それぞれの文字の数が100000を超えることはありません。
出力
小さな猫によって書かれた元のテキストの最大長さであるもの - 単一整数を持つ単一行。
サンプル入力
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit yeaphowmuchiloveyoumydearmother
サンプル出力
27
タイトル効果:出力文字列の2つの文字列が、もはや二つの文字列100,000、最長ではありません。
アイデア:
文字列の長さの2つの分子が、ハッシュ値は、文字列の長さの2つのサブ文字列の存在を確認します。
まず、比較ストリングの長さ、R値として短い長さを選択し、lは0の初期値(0は、共通文字列でないかもしれないことに注意!)。配列に格納されたハッシュ値を取得する文字列の接頭辞。
中間文字列の長さかどうかを決定する:ハッシュ値の中間の長さは、O(n)は、ハッシュ値の全ての中間の長さのために得られ、これをソート、配列に格納されています。中のすべての長い文字列のハッシュ値を取得するために、別の文字列が続き、binary_search文字列があるかどうかを調べます。
複雑さ:ソートLOWER_BOUND +(N- 2 logN個)
間違った場所:
符号なしでこの質問は、長い長い200に達する64 NATURALオーバーフローを、それが明示的には、ハッシュ値を計算するために使用される変数の全てがunsigned long long型でなければならないことに留意すべきである、それ以外の場合は異なる弾性係数になりますと、剰余演算を使用していませんエラー!
二分答案左值初始应设为0,可能没有公共子串!!
AC代码:
1 #include <iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 typedef unsigned long long ull; 7 const int maxn=1e5+10; 8 char stra[maxn],strb[maxn],strc[maxn]; 9 ull hasa[maxn],hasb[maxn]; 10 int lena,lenb; 11 ull mi[maxn]; 12 ull hasat[maxn],hasbt; //这里应该用ull,因为用来存储哈希值 13 bool yes(int x){ 14 hasat[0]=hasa[x-1]; 15 for(int i=1;i<lena-x+1;i++){ 16 hasat[i]=hasat[i-1]*31+stra[i+x-1]-'a'+1-(ull)(stra[i-1]-'a'+1)*mi[x]; 17 } 18 sort(hasat,hasat+lena-x+1); 19 hasbt=hasb[x-1]; 20 for(int i=1;i<lenb-x+2;i++){ 21 if(binary_search(hasat,hasat+lena-x+1,hasbt)) return true; 22 hasbt=hasbt*31+strb[i+x-1]-'a'+1-(ull)(strb[i-1]-'a'+1)*mi[x]; 23 } 24 25 return false; 26 } 27 int main(int argc, char** argv) { 28 mi[0]=1; //预处理31的各个幂 29 for(int i=1;i<maxn;i++) mi[i]=mi[i-1]*31; 30 while(scanf("%s%s",stra,strb)==2){ 31 lena=strlen(stra),lenb=strlen(strb); 32 if(lena>lenb){ //短的是字符串a 33 int temp=lena; 34 lena=lenb; 35 lenb=temp; 36 strcpy(strc,stra); 37 strcpy(stra,strb); 38 strcpy(strb,strc); 39 } 40 hasb[0]=strb[0]-'a'+1; //预处理字符串b 41 for(int i=1;i<lenb;i++){ 42 hasb[i]=strb[i]-'a'+1+hasb[i-1]*31; //为什么不从0开始?因为这样就容易出现不同字符串哈希值相等的情况 43 } 44 hasa[0]=stra[0]-'a'+1; //预处理字符串b 45 for(int i=1;i<lena;i++){ 46 hasa[i]=stra[i]-'a'+1+hasa[i-1]*31; //为什么不从0开始?因为这样就容易出现不同字符串哈希值相等的情况 47 } 48 // cout<<"ok"<<endl; 49 int l=0,r=lena,mid; //l应该初始时0!!!可能有0的情况!! 50 while(l<r-1){ 51 mid=(l+r)>>1; 52 if(yes(mid)) l=mid; 53 else r=mid-1; 54 } 55 // cout<<"okk"<<endl; 56 // cout<<l<<" "<<r<<endl; 57 for(int i=r;i>=l;i--){ 58 if(yes(i)){ 59 cout<<i<<endl; 60 break; 61 } 62 63 } 64 } 65 66 return 0; 67 }