题意:给出密文和明文,要求明文从密文某个下标开始对齐,每个位置上字母不一样。问有几种对齐方案。
思路:明文开始对齐位置的开头最大为len1-len2, 我们只要找出哪些位置不能作为开头,拿总数减去这些位置的个数就是方案数。找出密文中每个字母在的下标,以及明文中每个字母在明文串中的下标。
for(it=plain.begin();it!=plain.end();++it) 对于明文中的每个字符
{
char ch=it->first;
vector<int> vecp=it->second; 这些字符在明文中的下标
vector<int> vecen=encry[ch]; 这些字符在密文中的下标
for(int i=0;i<vecp.size();++i) 对于字母ch明文中的每个位置
{
for(int j=0;j<vecen.size();++j) 查找不能放的开头
{
if(vecen[j]-vecp[i]>=0&&vecen[j]-vecp[i]<=uplimit)
ans.insert(vecen[j]-vecp[i]);
}
}
}
密文中A的位置 9
明文中A的位置 0,3,5
比如对于明文中第一个A,不能放的开头是9,但是大于len1-len2了,不加入不能放队列
对于第二个A,不能放的位置是6(9-3)对应图中第6行
对于第三个A,不能放的位置是4(9-4)对应图中第4行
为什么会怎么想呢?因为1e4,0.5s,按时我们O(n)复杂度,就去扫一遍emmm
注意命名一定要规范,我写者写者写岔了后来调了好一会,浪费了很多时间
#include<iostream>
#include<set>
#include<string>
#include<vector>
#include<map>
using namespace std;
string s,t;
map<char,vector<int> > encry;
map<char,vector<int> > plain;
set<int> ans;
int main()
{
cin>>s>>t;
int len1=s.size();
int len2=t.size();
for(int i=0;i<len1;++i)
{
char ch=s[i];
// cout<<a-65<<endl;
//cout<<i<<endl;
encry[ch].push_back(i);
}
for(int i=0;i<len2;++i)
{
char ch=t[i];
plain[ch].push_back(i);
}
//cout<<len1<<' '<<len2<<endl;
int uplimit=len1-len2;
map<char,vector<int> >::iterator it;
for(it=plain.begin();it!=plain.end();++it)
{
char ch=it->first;
vector<int> vecp=it->second;
vector<int> vecen=encry[ch];
//cout<<ch<<' '<<vecp.size()<<' '<<vecen.size()<<endl;
for(int i=0;i<vecp.size();++i) //对于每个偏移序
{
for(int j=0;j<vecen.size();++j)
{
if(vecen[j]-vecp[i]>=0&&vecen[j]-vecp[i]<=uplimit)
ans.insert(vecen[j]-vecp[i]);
}
}
}
int res=uplimit+1-ans.size();
// cout<<uplimit<<endl; //
// cout<<ans.size()<<endl; //0
cout<<res<<endl;
return 0;
}