試合
そこBが$ L_ {B} $プレフィックスの長さである二つの文字列A、B、Aが、である今端Bに文字を記入し、サフィックスBを解く最大プレフィックスはに等しいです。
$ T <= 10、L_ {B} <= 100000、L_ {B} <= L_ {A} <= 2 * L_ {B} $、すべて小文字であります
問題の解決策
考慮に入れてに加えて、最後の文字が接頭辞Aであるので、変換後のプレフィックスBはBでない場合、その後、Bはサフィックスに等しい最大プレフィックスを求めています。
ライン上でKMPと
#include <cstdioを> する#include <CStringの> する#include <iostreamの> する#include <アルゴリズム> 使用して 名前空間STDを、 const int型 MAXN = 200005 ; int型T、レナ、LENB。 チャー C [ 2 ]、S [MAXN]、T [MAXN]。 INT [MAXN]失敗。 ボイドKMP(){ [失敗0 ] =失敗[ 1 ] = 0 。 以下のために(int型 iは= 1 ; iは<LENB; iが++ ){ int型、T =が失敗[I]。 同時に(!T && S [I] = S [T])T = [T]失敗。 失敗[I + 1 ] =(S [I] == S [T] T +?1:0 )。 } } int型のmain(){ freopenは(" string.in "、" R " 、STDIN)。 freopenは(" string.out "、" W " 、STDOUT)。 scanf関数(" %のD "、&T)。 一方、(T-- ){ scanf関数(" %D%D%S%S "、&レナ&もし(S [LENB] == C [ 0 ]){のprintf(" %d個の\ n "、LENB + 1)。引き続き;} S [LENB ++] =のC [ 0 ]。 KMP(); printf(" %Dを\ n " 、[LENB]失敗); } }
帰宅します
図N点mエッジを有するが、1からnまでの点を通っていきます。
M <= 2N、N <= 200000、データの複数のセット
問題の解決策
間違った考えを与える:最短の方法で特定のポイントを通過しなければならない、必要なポイントは、ポイントを切断しなければならないことを検討してください。だから、tarjan決定されるカットポイントの後、二回はBFS最短ラン、最終的な判断を見つけます。
なぜそれが間違っていますか?これらは単なる自然であり、結論を出すことはできませんので。
最も重要なのは、カット点を保証することはできないであり、nは1を通信していません
したがって、かどうかサブツリーNを考慮して、tarjanの記録時に決定することができます。
コードのコメントで詳細
書式#include <キュー> の#include <cstdioを> する#include <CStringの> の#include <iostreamの> の#include <アルゴリズム> 使用して 名前空間はstdを、 const int型 MAXN = 200005 ; const int型 INF = 0x3f3f3f 。 int型、T、N、M、CUR、CNT。 int型のヘッド[MAXN]。 int型DFN [MAXN]、低[MAXN]。 int型のトップ、STA [MAXN]。 BOOL 切断[MAXN]、CON [MAXN]。 INT DIS [MAXN] [ 2 ]。 構造体のエッジ{ int型のX、Y、次; } E [MAXN<< 3 ]。 テンプレート < クラス T>インラインボイドリード(T&X){ X = 0。int型の F = 0 ; チャー CH = GETCHAR()。 一方、 {F | =(CH ==(isdigit(CH)!)' - '); CH = GETCHAR();} ながら(isdigit(CH)){X =(X << 1)+(X << 3)+(CH ^ 48)、CH = GETCHAR();} 、X = F?- X:X; } ボイド追加(int型のx、int型 Y){ E [ ++ CNT] = (エッジ){X、Y、ヘッド[X]}。 ヘッド[X] = CNT。 } ボイドのinit(){ CNT =人気= CUR = 0 。 memsetの(カット、偽、はsizeof (カット)); memsetの(詐欺、虚偽、はsizeof (CON)); memsetの(頭、0、はsizeof (ヘッド))。 memset(DFN、0、はsizeof (DFN))。 memsetの(低い、0、はsizeof (低))。 以下のために(int型 i = 1 ; iが<= N; iは++します) DIS [i]は[ 0 ] = DIS [I] [ 1 ] = INF。 } ボイド tarjan(int型のx、int型FA){ int型 NUM = 0。もし(x == N)CON [X] = 真。 低[X] =のDFN [X] = ++ CUR。 以下のために(int型 I =ヘッド[X]; I; I = E [i]は.next){ int型、Y = E [I] .Y。 もし(!DFN [Y]){ tarjan(Y、X)。 低[X] = 分(低[x]は、低[Y])。 CON [X] | = CON [Y]。 もし(DFN [X] <=低[ Y] && CON [Y])// CON [Y]を分析:DFN [X] <=ロー[ためとき yは】 ときカットポイントは、Yサブツリー意志別知ります最終結果は、xが判定された場合に別のサブツリーは、N-含有 [X] =カットtrueに; } そう IF低[X] =(Y = FA!)分(低[x]は、DFN [Y]); } } ボイド解決(){ 読み取り(N-);リード(M) のinit() のための(INT I = 1 ; I <= M; I ++ ){ int型のX、Y、 リード(X);リード(Y)、 IF( Y == X)続け、 追加(X、Y)、追加(Y、X); } Tarjan(1、0); 以下のために(int型 I = 2、iがn <; iは++ ) 場合(切断[i])と STA [ ++トップ] = I。 printf(" %d個の\ n " 、上)。 用(int型 i = 1 ; iが=トップ<; Iは++ ) のprintf(" %dの" 、STA [I])。 putchar(10 )。 } int型のmain(){ freopenは(" home.in "、" R " 、STDIN)。 freopenは(" home.out "、" W " 、STDOUT)。 (t)を読み出します。 一方、(t-- )()を解きます。 } / * 2 4 3 1 2 2 3 3 4 5 1 2 2 3 3 4 4 4 1 / *