NC231634. 小哈的魔法咒语
描述
输入描述
第一行输入一个整数, 表示咒语字符串的长度。
第二行输入长为 的字符串表示咒语, 由小写字母组成。
第三行为 个整数,第 个整数代表念完第 个咒语所需法力值 (。
输出描述
输出一个整数表示小哈通过考试的最小法力值消耗。
示例1
输入:
2 ac 1 2
输出:
4
示例2
输入:
5 aacaa 1 2 3 4 5
输出:
50
说明:
对于样例1:没有额外限制,小哈先念,再念 。所需法力值为 ,可以证明 4 是小哈消耗的最小法力值。C++ 解法, 执行用时: 63ms, 内存消耗: 6996K, 提交时间: 2021-12-12 14:28:03
#include <iostream> #include <vector> #include <queue> using namespace std; const int N = 100010; int v[N]; int nxt[N], fa[N], siz[N]; vector<int> edge[N]; struct node { int x,siz; long long w; bool operator<(const node b)const{return w*b.siz<b.w*siz;} }; priority_queue<node> q; long long ans; int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); } void push(int x) { q.push(node{x,siz[x],v[x]}); } void merge(int f,int x) { ans+=1ll*siz[f]*v[x]; // cout<<"merge "<<f<<" "<<x<<" "<<ans<<endl; v[f]+=v[x]; siz[f]+=siz[x]; } int main() { int n; string s; int i, j; int x, f; cin >> n; cin >> s; for(i = 1; i <= n; i ++) cin >> v[i]; j=nxt[0]=-1; i=0; while(i<n){ while(-1!=j && s[i]!=s[j])j=nxt[j]; nxt[++i]=++j; } // for(i=1;i<=n;i++)cout<<nxt[i]<<' ';cout<<endl; for(i = 1, ans = 0; i <= n; i ++) { fa[i] = i; siz[i] = 1; ans += v[i]; push(i); } // cout<<ans<<endl; while(!q.empty()) { x=q.top().x; // cout<<x<<endl; q.pop(); if(x!=find(x))continue; x=find(x); fa[x]=f=find(nxt[x]); merge(f,x); if(f)push(f); } cout << ans << endl; return 0; }