Description
话说上回涂山小八进入“时空之门”,却不是回到现实世界,而是一间方正小屋。随着时空之门缓缓关上,小八才看清墙上排着很多奇怪的字符。正奇怪着,小屋内响起了说话声。
“你现在本应已回到现实世界,但你来的时间太久,能量已经用光,无法直接通过时空之门,所以才会来到此地。唯今之计只有获得巴啦啦能量,否则你依然会被永远留在此地。”
“如何获得巴啦啦能量?”
“看见墙上的巴啦啦密文了吗?我现在给你一个能量之匙,从巴啦啦密文中找出巴啦啦能量串即可获得巴啦啦能量。巴啦啦能量串是所有包含能量之匙的最小串,切记,若找到多个符合要求的巴啦啦能量串,不可贪多,只需带走第一个,否则前功尽弃。”
Input
输入数据有多组,每组数据输入第一行输入字符串巴啦啦密文S,第二行输入字符串能量之匙T,S长度lens(1≤lens≤105
),T长度lent(1≤lent≤105 )(输入不包含空格),输入字符区分大小写。
Output
对于每组输入数据,输出找到的巴啦啦能量串,每组输出占一行。如果找不到巴啦啦能量串,输出一个空行。
Sample Input
ADOBECODEBANC
ABC
ABCDA
BD
Sample Output
BANC
BCD
思路
给出两个字符串 S 和 T, 询问 S 中长度最小的位置最靠前
的包含 T 的子串, 如果不存在, 只输出换行
首先 O(N2) 复杂度肯定过不了,我们得找一找优化的方法
用两个标记数组分别存储T串中的字符出现的次数和是否出现过
用l记录当前的左端点的位置,minl记录更新后的左端点的位置,minn记录要求的子串的长度,cnt记录当前已经出现了几个T串中的字符
然后遍历S串,跳过没有出现过的字符,碰见出现过的字符,就给他的出现次数-1,当减一之后的然后判断当前的出现次数是否>=0,如果是的话就用cnt记录一下,当cnt的数量和T串的长度一样时,代表当前已经有一个区间包含这个T串了,我们根据当前的左右端点尝试更新区间,然后将左边界右移,在右移左边界的过程中如果碰见已经在T串出现过的字符,就给他的出现次数+1,当他的出现次数加到正数时,cnt的值减一(当前我们的区间已经不包含T串中的所有字符了),所以右移左边界停止,继续在右边界找,直到包含整个T串,然后再尝试更新左边界。。。
总体的思路就是,枚举包含T串的区间,然后更新边界,找出最小的
这样,就以线性的复杂度求出要求的子串,最后输出找到的区间的串就是答案
还可以用STL的map做,思路是一样的
代码1
#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e5+20;
char s[N],t[N];
int vis[200];//标记出现的次数
int sear[200];//标记是否出现过
int main()
{
while(~scanf("%s%s",s,t))
{
mem(vis,0);
mem(sear,0);
int tlen=strlen(t);
int slen=strlen(s);
for(int i=0; i<tlen; i++)
{
vis[t[i]]++;
sear[t[i]]=1;
}
int cnt=0,l=0,minl=0,minn=slen+1;
for(int r=0; r<slen; r++)
if(sear[s[r]])
{
if(--vis[s[r]]>=0)
cnt++;
while(cnt==tlen)
{
if(r-l+1<minn)
minl=l,minn=r-l+1;
if(sear[s[l]])
if(++vis[s[l]]>0)
cnt--;
l++;
}
}
if(minn>slen) printf("\n");
else
{
for(int i=minl; i<minl+minn; i++)
printf("%c",s[i]);
printf("\n");
}
}
return 0;
}
代码2
#include <stdio.h>
#include <iostream>
#include <string>
#include <map>
using namespace std;
string minWindow(string S, string T)
{
map<char, int> m;
for(int i = 0; i < T.size(); ++ i)
m[T[i]]++;
int cnt = 0, l = 0, minl = 0, minsize = S.size() + 1;
for(int r = 0; r < S.size(); ++ r)
if(m.find(S[r]) != m.end())
{
if(-- m[S[r]] >= 0)
++ cnt;
while(cnt == T.size())
{
if(r - l + 1 < minsize)
minl = l, minsize = r - l + 1;
if(m.find(S[l]) != m.end())
if(++ m[S[l]] > 0)
-- cnt;
++ l;
}
}
if(minsize>S.size())
return "";
return S.substr(minl, minsize);
}
int main()
{
string s, t;
while(cin >> s >> t)
{
string ans = minWindow(s, t);
cout << ans << endl;
}
return 0;
}