题目:
yah has n strings <s1,⋯,sn>, and he generates a sequence P by two steps:
- P=<s1,⋯,sn>
- Replace each si with all prefixes of itself.
An example is:
- the n strings are < aab,ab >
- first, P =< aab,ab >
- then, P =< a,aa,aab,a,ab >
There are 26 positive integers d1,⋯,d26 that denote the difficulty to identify lowercase English letter a,b,⋯,z for yah.
The difficulty to identify a string strstr is (i=1∏∣str∣dstri) mod m
Now, yah wants to calculate: for each string si(i=1,⋯,n), the number of strings in P that is prefix of si and more difficult than si.
Input
The first line contains two integers n,mn,m(1≤n≤105,1≤m≤2×105).
The second line contains 26 positive d1,⋯,d26, 0^50≤di≤105.
The following n lines, each line contains a string, the ith lines contains si, the sum of length of all strings is not great than 2×105.
Output
The only line contains n integers, the ith integer denoting the number of strings in P that is prefix of si but more difficult to identify for yah.
题意:
输入n个字符串,求大于字符串i 的 值 的 前缀的 个数(值= (字母*对应的权值) 取余m),主要求前缀的个数
字典树模板变化
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
typedef long long ll;
using namespace std;
int root;
int w = 1;
int trie[400500][30];
int num[400500];
void build_trie(string s, int len){
root = 0;
for(int i = 0; i < len; i++){
int k = s[i] - 'a';
if(trie[root][k] == 0){
trie[root][k] = ++w;
}
root = trie[root][k];
num[root]++;
}
}
int query(string su){
int len = su.size();
root = 0;
for(int i = 0; i < len; i++){
int k = su[i] - 'a';
if(trie[root][k] == 0){
return 0;
}
root = trie[root][k];
}
return num[root];
}
int cou = 0;
int main(){
string s[150000];
memset(trie, 0, sizeof(trie));
memset(num, 0, sizeof(num));
int n, m;
cin >> n >> m;
int a[30];
memset(a, 0, sizeof(a));
for(int i = 0; i < 26; i++){
cin >> a[i];
}
for(int i = 0; i < n; i++){
cin >> s[i];
int x = s[i].size();
build_trie(s[i], x);
}
for(int i = 0; i < n; i++){
int len = s[i].size();
ll tmp = 1;
ll cnt = 0;
ll k = 1;
string su;
for(int j = 0; j < len; j++){
k = (k * a[s[i][j]-'a']) % m; // 字符串 i的值
}
ll ans = 0;
for(int j = 0; j < len; j++){
su = s[i].substr(0, j+1);
tmp = (tmp * a[s[i][j]- 'a'] ) % m; 字符串i的前缀的值
if(tmp > k){
ans = ans + query(su); // 查找个数
}
}
cout << ans << " ";
}
cout << endl;
return 0;
}
用暴力的方法,用map存字符前缀出现的次数
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
typedef long long ll;
using namespace std;
map<string, ll> ma;
ll a[30], k[200005];
int main(){
int n, m;
cin >> n >> m;
string s[100005];
memset(a, 0, sizeof(a));
for(int i = 0; i < 26; i++){
cin >> a[i];
}
for(int i = 1; i <= n; i++){
k[i] = 1;
cin >> s[i];
int len = s[i].size();
for(int j = 0; j < len; j++){
string ss;
ss = s[i].substr(0,j+1);
ma[ss]++;
k[i] = (k[i] * a[s[i][j]-'a']) % m;
}
}
for(int i = 1; i <= n; i++){
int len = s[i].size();
ll w = 1, ans = 0;
for(int j = 0; j < len; j++){
w = (w * a[s[i][j]-'a']) % m;
if(w > k[i]){
string ss;
ss = s[i].substr(0,j+1);
ans = ans + ma[ss];
}
}
cout << ans << " ";
}
cin >> n;
return 0;
}