题目
https://cn.vjudge.net/problem/FZU-2280
题意
给你n和字符串和权值,m次操作,
1 x y 把x的权值该为y
2 x 问有多少字符串后缀为x 并且权值小于等于x的权值
思路
字符串hash 然后暴力
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
typedef unsigned long long ll;
const ll base = 183;
const ll mod = 1e9+7;
char s[1100][1110];
ll ha[1100][1100],p[1100];
int val[1100];
int len[10004];
void init(int id)
{
ha[id][0] = 0;
for(int i = 1;i <= len[id];i++) ha[id][i] = ((ha[id][i-1]*base) + s[id][i]);
}
ll Hash(int id,int l,int r)
{
return (ha[id][r] - ha[id][l-1]*p[r-l+1]);
}
int main()
{
int T;
p[0] = 1;
for(int i = 1;i <= 1000;i++) p[i] = (p[i-1]*base);
scanf("%d",&T);
while(T--)
{
int n;
memset(val,0,sizeof(val));
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%s %d",s[i]+1,&val[i]);
len[i] = strlen(s[i]+1);
init(i);
}
vector<int> v[1100];
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
{
if(strlen(s[i]+1) > strlen(s[j] + 1)) continue;
ll x = Hash(i,1,len[i]);
ll y = Hash(j,len[j]-len[i]+1,len[j]);
// cout<<i<<" "<<j<<" ";
// cout<<x<<" "<<y<<endl;
if(x == y)
{
v[i].push_back(j);
}
}
}
int m;
scanf("%d",&m);
while(m--)
{
int ok;
scanf("%d",&ok);
if(ok == 1)
{
int u,v;
scanf("%d%d",&u,&v);
val[u] = v;
}
else
{
int x;
int ans = 0;
scanf("%d",&x);
for(int i = 0;i < v[x].size();i++)
{
int id = v[x][i];
// cout<<id<<endl;
if(val[id] <= val[x])
{
ans++;
}
}
printf("%d\n",ans);
}
}
}
return 0;
}