prefix
本题是要求你找出一个组内比原字符串权值大的前缀,而一个组内包含了其他字符串的前缀,但可能也适配于这个字符串。所以说要记录这些前缀的个数才能解出这个问题。
一个方法是用std::map这样的一个红黑树字典,可以直接把string类型的前缀出现次数用int/ll类型的数字统计下来。然后再计算各前缀的权值与个数之积,逐一与原字符串权值进行比对,即可得到答案。
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
string strs[500000];
ll identify[40],ans[500000];
ll cost[500000];
map<string,ll>prefix;//记录前缀出现次数
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll n,m;
cin>>n>>m;
for(int i=1;i<=26;i++)
cin>>identify[i];
for(int i=1;i<=n;i++)
cin>>strs[i];
for(int i=1; i<=n; i++)
{
string tmp="";
ll tmpr=1;
for(int j=0; j<strs[i].size(); j++)
{
tmp+=strs[i][j];
prefix[tmp]++;//录入前缀
tmpr=(tmpr*identify[strs[i][j]-'a'+1])%m;
}
cost[i]=tmpr;
}
for(int i=1;i<=n;i++)
{
string tmp="";
ll tmpcost=1;
for(int j=0;j<strs[i].size();j++)
{
tmp+=strs[i][j];
tmpcost=(tmpcost*identify[strs[i][j]-'a'+1])%m;
if(tmpcost>cost[i])
ans[i]+=prefix[tmp];
}
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}
不过既然涉及到前缀,还有一个数据结构可满足需求,即字典树。
先来简明介绍一下字典树:字典树是一个26叉树,每一个节点对应26个子结点,也就是不同的英文字母。root,根节点不存储任何信息,它的子结点才存储信息,通过从根节点到最底下的子结点的遍历,就可以近似于遍历了一个英文单词或一个前缀。这需要一个二维数组或者一个结构体数组实现。(模板题HDU1251)
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
int trie[1000030][30], sum[1000030];
ll cnt = 1;
void ins(char text[])//插入一个单词
{
ll root = 1;
ll lim = strlen(text);
for (int i = 0; i < lim; i++)
{
ll tmp = (text[i] - 'a'+1);
if (trie[root][tmp] == 0)//如果当前节点没有这个字母对应的子结点,那么创建
trie[root][tmp] =++cnt;
sum[trie[root][tmp]]++;//记录从第一个节点到现在的前缀或是单词出现的次数
root = trie[root][tmp];//迭代搜索
}
return;
}
ll query(char text[])
{
ll root = 1;
ll lim = strlen(text);
for (int i = 0; i < lim; i++)
{
ll tmp = (text[i] - 'a'+1);
if (trie[root][tmp] == 0)//没有这样的子结点
return 0;
root = trie[root][tmp];
}
return sum[root];
}
char input[55555];
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
while (cin.getline(input,11))//未知数量但已知长度的C++式输入,C可用GETS
{
if (input[0] == NULL||strlen(input)==0)
break;
else
ins(input);
}
while (cin >> input)
cout << query(input) << endl;
return 0;
}
而我们恰好可以使用字典树的记录前缀数量的功能来解决这个问题,那么它的查询也就对应着前缀出现的个数。仍然是一番计算就可以解决问题。
#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
int trie[125000][30], ans[125000],cost[925000],sum[125000],totalcost[125000];
int identify[30];
string strs[125000];
ll cnt = 2;
void ins(string info,int mod)
{
ll root = 1;
for (int i = 0; info[i]; i++)
{
ll next = (info[i] - 'a' + 1);
if (trie[root][next] == 0)
trie[root][next] = cnt++;
sum[trie[root][next]]++;
//ll current = cnt - 1;
//if (cnt == 2)
// cost[trie[root][next]] = identify[next] % mod;
//else
// cost[trie[root][next]] = (cost[trie[current][next]] * identify[next]) % mod;
root = trie[root][next];
}
return;
}
int query(string info,int mod,int index)//查询前缀出现次数
{
ll root = 1;
for (int i = 0; info[i]; i++)
{
ll next = (info[i] - 'a' + 1);
if (trie[root][next] == 0)
return 0;
root = trie[root][next];
}
//if(info.size()==strs[index].size())
// cout << cost [root]<< endl;
//if (cost[root]> totalcost[index])
return sum[root];
//else
// return 0;
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= 924009; i++)
cost[i] = 1;
for (int i = 1; i <= 26; i++)
cin >> identify[i];
for (int i = 1; i <= n; i++)
{
cin >> strs[i];
ins(strs[i],m);
ll tmp = 1;
for (int j = 0;strs[i][j]; j++)
{
tmp = (tmp*identify[strs[i][j] - 'a' + 1]) % m;
}
totalcost[i] = tmp;//计算原字符串权值
}
//for (int i = 1; i <= n; i++)
// cout << "Total:" << totalcost[i] << endl;
for (int i = 1; i <= n; i++)
{
string tmp = "";
ll tmpvalue = 1;
for (int j = 0;j<strs[i].size()-1; j++)
{
tmp += strs[i][j];
tmpvalue = (tmpvalue*identify[strs[i][j] - 'a' + 1]) % m;
if(tmpvalue>totalcost[i])
ans[i] += query(tmp, m, i);//计算
}
}
for (int i = 1; i <= n; i++)
cout << ans[i] <<" ";
return 0;
}

浙公网安备 33010602011771号