題目背景
yazid 和 tiffany 喜歡字串問題。在這裡,我們將給你介紹一些關於字串的基本概念。
對於乙個字串 $s$, 我們定義 $\lvert s\rvert$ 表示 $s$ 的長度。
接著,我們定義該串的子串 $s\left( \right)$ 表示由 $s$ 中從左往右數,第 $l$ 個字元到第 $r$ 個字元依次連線形成的字串,特別地,如果 $l < 1$ 或 $r > \lvert s\rvert$ 或 $l > r$,則 $s\left( \right)$ 表示空串。
我們說兩個字串相等,當且僅當它們的長度相等,且從左至右各位上的字元依次相同。
我們說乙個字串 $t$ 是 $s$ 的**字首**,當且僅當 $s\left( 1,\lvert t\rvert\right)=t$。
兩個字串 $s,t$ 相加 $s+t$ 表示的是在 $s$ 後緊挨著寫下 $t$ 得到的長度為 $\lvert s\rvert+\lvert t\rvert$ 的字串。
題目描述
現有乙個字串 $s$。
tiffany 將從中劃出 $n_a$ 個子串作為 a 類串,第 $i$ 個($1\leq i\leq n_a$)為 $a_i = s\left( la_i, ra_i\right)$。
類似地,yazid 將劃出 $n_b$ 個子串作為 b 類串,第 $i$ 個($1\leq i\leq n_b$)為 $b_i = s\left( lb_i, rb_i\right)$。
現額外給定 $m$ 組支配關係,每組支配關係 $\left( x,y\right)$ 描述了第 $x$ 個 a 類串**支配**第 $y$ 個 b 類串。
求乙個**長度最大**的目標串 $t$,使得存在乙個串 $t$ 的分割 $t=t_1 + t_2 +\dots +t_k$($k\geq 0$)滿足:
- 分割中的每個串 $t_i$ 均為 a 類串:即存在乙個與其相等的 a 類串,不妨假設其為 $t_i = a_$。
- 對於分割中所有相鄰的串 $t_i , t_$($1\leq i < k$),都有存在乙個 $a_$ 支配的 b 類串,使得該 b 類串為 $t_$ 的字首。
方便起見,你只需要輸出這個最大的長度即可。
特別地,如果存在無限長的目標串(即對於任意乙個正整數 $n$,都存在乙個滿足限制的長度超過 $n$ 的串),請輸出 $-1$。
solution
首先考慮暴力建圖:a向支配的b連,b向字首包含它的連。然後跑拓撲序dp。 40『(我這咋只有20)
用sam優化:用反串建,則x為x的後代的字首。
那麼可以把par樹連起來,然後支配邊照常連,邊數2n 。80』
不能滿分是因為如果b[i]>a[i],連邊後可能兩個b被壓在了同乙個節點,但是乙個可以被支配,乙個不行。
把乙個sam節點上的所有串按長度排序,從長度小的開始連,每次當前點與它的上乙個b點。相當於串了起來。
這樣子如果a能支配某乙個b1,那麼他只會連到這個b1,然後再間接的連到乙個比b1長的b2...
而如果b2是某個串的字首,那麼b1也是。
於是就好了。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9view code#define maxn 800005
10using
namespace
std;
11int
t,na,nb,m,cnt,rt,la,al;
12int head[maxn],tot,pl[maxn],f[maxn][22],out
[maxn],top[maxn];
13long
long dp[maxn];char
ch[maxn];
14 vectorg[maxn],p[maxn];
15struct nodee[maxn*2
];16
struct
nos[maxn];
19struct
nodea[maxn],b[maxn];
22void
q()28 cnt=rt=la=1;tot=0
;29 memset(f,0,sizeof
f);30 memset(s,0,sizeof
s);31}32
void ins(int c,int
id)47}48
}49void dfs(int k,int
fa)53
bool cmp(int a,int
b)61
void add(int t1,int
t2)65
void
init()
70 scanf("
%d",&na);for(int i=1;i<=na;i++)scanf("
%d%d
",&a[i].l,&a[i].r),a[i].len=a[i].r-a[i].l+1
;71 scanf("
%d",&nb);for(int i=1;i<=nb;i++)scanf("
%d%d
",&b[i].l,&b[i].r),b[i].len=b[i].r-b[i].l+1;72
for(int i=1;i<=cnt;i++)g[s[i].par].push_back(i);
73 dfs(rt,0
);74
for(int j=1;j<=20;j++)
75for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1
];76
for(int i=1;i<=na;i++)
81 p[t].push_back(cnt+i);82}
83for(int i=1;i<=nb;i++)
88 p[t].push_back(cnt+na+i);89}
90for(int i=1;i<=cnt;i++)sort(p[i].begin(),p[i].end(),cmp);
9192
for(int i=1;i<=cnt;i++)
99 top[i]=lb;
100}
101for(int i=1;i<=cnt;i++)
102if
(s[i].par)
105 cin>>m;
106for(int i=1,t1,t2;i<=m;i++)
110 al=cnt+na+nb;
111}
112void
tp()
122}
123for(int i=1;i<=al;i++)if(out[i]>0)
124long
long ans=0
;125
for(int i=1;i<=al;i++)ans=max(ans,dp[i]);
126 cout
127}
128int
main()
135return0;
136 }
字串問題 翻轉字串
題目 給定乙個字元型別的陣列chas,請在單詞間做逆序調整,只要做到單詞順序逆序即可,對空格的位置沒有特別要求。例如把chas看成字串為 i love you 調整成 you love i 補充題目 給定乙個字元型別的陣列chas和乙個整數size,請把大小為size的左半區整體移到右半區,右半區整...
字串問題
char str1 abcd char str2 efgh str1 str2 這個操作是合法的,結果也是正確的 這兩個字串都是儲存在棧上,可以修改其中的內容。其中,str1 str2相當於把str2字串的第乙個字元 e 賦給了str1的第乙個字元,因此,str1就變成了 ebcd 但是如果用字串指...
字串問題
ll是什麼?這都不知道的話,別說自己是程式猿啊!longlong?肯定是lovelive啊!qwb為了檢驗你是否是真正的程式猿,決定出道題考考你 現在程式會輸入一行字串,如果恰好是lovelive 不區分大小寫 就輸出yes,否則輸出no。輸入有多組 組數不超過100 每組輸入一行字串 字串長度不超...