题解 P3500 【[POI2010]TES-Intelligence Test】
考虑暴力。对于每一个询问,我们都维护两个指针,分别扫描原串
时间复杂度
容易发现,其实没必要对于每一个询问的串都扫描一次
扫描
如何求出扫描到第
时间复杂度
#include <cstdio>
#include <vector>
#include <cctype>
#include <cstring>
#include <algorithm>
#define mp make_pair
using namespace std;
const int N=1000010;
int n,m,len,a[N],b[N],st[N];
bool ans[N];
vector<pair<int,int> > pos[N],cpy;
// pos[x][j].first 表示第 j 个需要匹配的数字为 x 的 b 串编号是几
// pos[x][j].second 表示第 j 个需要匹配的数字为 x 的 b 串 现在匹配到哪个位置了
int read()
{
int d=0,f=1; char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) d=(d<<1)+(d<<3)+ch-48,ch=getchar();
return f*d;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
a[i]=read();
m=read();
for (int i=1,x;i<=m;i++)
{
x=read(); st[i]=len+1; //省空间,将所有 b 串压缩在一个数组里
for (int j=1;j<=x;j++)
b[++len]=read();
pos[b[st[i]]].push_back(mp(i,st[i]));
// 一开始所有串都匹配到第一个位置
}
st[m+1]=len+1;
for (int i=1;i<=n;i++)
{
cpy.clear();
for (int j=0;j<pos[a[i]].size();j++) // 枚举所有能匹配的串
{
int k=pos[a[i]][j].first,p=pos[a[i]][j].second;
if (p+1==st[k+1]) ans[k]=1; // 这个串已经全部匹配完了
else cpy.push_back(mp(k,p+1)); //记录匹配下一位
}
pos[a[i]].clear();
for (int j=0;j<cpy.size();j++) //将上面匹配的串的下一位插入
{
int k=cpy[j].first,p=cpy[j].second;
pos[b[p]].push_back(mp(k,p));
}
}
for (int i=1;i<=m;i++)
if (ans[i]) printf("TAK\n");
else printf("NIE\n");
return 0;
}