NOIPアナログ929

試合

そこ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 +?10 )。
    } 
} 

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 = 0int型の 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(10);
    以下のために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 
/ *

 

おすすめ

転載: www.cnblogs.com/sto324/p/11620730.html