比賽時隊友有想法了我就一直在出數據了。
然而那個想法是錯的。到快結束的時候才驗證了是錯的。
都怪自己太懶,沒有驗證正確性就盲目地同意隊友寫,然後兩個人越改越亂,要多思考啊。
然後比賽快結束的時候我想到了新的解法。就是從後往前匹配。然而就是再給半個小時也做不出來,因爲少考慮了一些情況。
題意:給出兩個串s,t……現在需要在s的任意字符x後面添加一個字符y(y≠x),問s有沒有辦法變成t。
思路:
1、把s串作爲基準,把t從後往前匹配。
2、上一步有一個遺漏,那就是沒有判斷第一個字符,最前面的加字符操作一定是在第一個字符之後,所以s和t的第一個字符必須相同。
3、解釋一下第一步中爲什麼如果出現多個x,和最後一個x匹配是最優的呢,假如s是abx,t是abbx,那麼新加入的這個b肯定是要放在a之後加進去的,如果新加入的這個b放在原來b之後,那麼就會匹配失敗啦~然後現在第二步之後(噢現在是10:43)也就是s中的第一個字符和t中的第一個字符匹配,其餘的不變 。
4、但是如果s 是 aaa,t是aaabaaa,那就不對了。(啊我真的好跳啊是不是有多動症)也就是說第一個字符必須s和t相同的,特例必須推廣到s和t相同並且該字符在s中和第一個字符相同的所有情況。然後就可以過了。(替啦這題解寫得我自己都看不下去了語文水平太弱了TAT)
注意事項:
1、據說memset比for快。也就是用時:for整個數組 > memset整個數組 > for n+3 > memset n+3, 但是用最快的memset n+3 如果你傻逼了就會莫名wa。這次就是先memset整個數組了,然後是T了,改成memset n+5 才變成wa
2、數據怎麼想出來的呢?首先原來的做法問題出在第一個字符上,那麼第一個字符問題解決了之後會不會對第一個字符緊接着的第二個字符有影響呢?如果第二個字符和第一個相同或者不同,會有哪些影響呢?改策略的時候,要考慮與之相關的所有情況。
以下是代碼。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define SIZE_N 100005
using namespace std;
char s[SIZE_N],t[SIZE_N];
int markt[SIZE_N];//,markss[SIZE_N];
int main()
{
int T;
scanf("%d",&T);
while (T--){
scanf("%s",s);
scanf("%s",t);
int suc = 1;
int lenss,lentt;
for (lenss = 0; s[lenss]; lenss++);
for (lentt = 0; t[lentt]; lentt++);
//memset(markss,0,sizeof(int) * (lenss+ 5));
memset(markt,0,sizeof(int) * (lentt+5));//第一次交t了,改一下memset。826的934再交一發
//果然只用372ms了……這道題時間卡的好緊啊……memset都能T了一次
int j = lentt - 1;
if (t[0]!= s[0]|| lenss > lentt){
suc = 0;
}else{
int nows = 0;
for (int i = 0; i < lentt; i++)//改一下第一個元素的處理。再交第n+1次。10:55
if (t[i] == t[0]){
if (t[i] == s[nows]){
markt[i] = 1;
nows++;
}else{
suc = 0;
break;
}
}else{
break;
}
for (int i = lenss - 1; i >= 0; i--){
while ( j >= 0 && t[j] != s[i]){
j--;
}
if (j < 0){
suc = 0;
break;
}
if (i >= nows)
markt[j] = 1;
j--;//避免同樣的元素被重複標記
}
}
if (suc != 1){
puts("No");
}else{
puts("Yes");
}
}
return 0;
}
//我知道這種做法錯在哪了!aaa和aaabaaa。就會匹配後兩個a和第一個a
//還有一組樣例就是aaa和aaaabaaa。