字串極值題解
阿新 • • 發佈:2021-07-01
題目分析
現將字串轉化為數列,對於一個序列:
在列舉序列時,記 \(i\) 為當前數的下標。
可以記錄 \(now\) 值為最大的 \([k,i]\) 中序列和的值 \((1\leq k \leq i)\),\(ans\) 為最終的答案。
令初始 \(now=0\),每讀入一個新數 \(x\):
- 如果 \(x>0\),\(now+=x\),\(ans=\max(ans,now)\);
- 如果 \(x<0\),且 \(now+x>0\),\(now+=x\);
- 如果 \(x<0\),且 \(now+x \leq 0\),直接令 \(now=0\)。
上面這個過程不能解決序列全是負數的情況,如果出現序列中全是負數的情況,特判即可:
因為序列中沒有數值為 \(0\) 的數,所以在任意時刻,如果 \(now=0\),則目前序列中的數都為負數。只需要根據這一特性特判即可。
參考程式碼
#include <iostream> #include <cstdio> #include <cstring> #define ll long long using namespace std; int change(char ch) //將字母轉換為對應的值 { int ans; if ('a' <= ch && ch <= 'z') ans = -(ch - 'a' + 1); else ans = (ch - 'A' + 1); return ans; } ll T, n, maxn, now, len; string str; int main() { cin >> T; while (T--) //多組資料 { cin >> str; len = str.size(); //求串的長度 now = change(str[0]); //掃描第一個數,賦值給 now maxn = now; //此時更新答案 if (now < 0) //如果 now 為負數,直接捨棄前面 now = 0; for (int i = 1; i < len; ++i) //字串下標從0開始 { ll x = change(str[i]); //數 if (x > 0) //正數 { now += x; maxn = max(now, maxn); } else //負數 { if (now + x < 0) //加上 x 之後使得 now<0 { if (now == 0) //特判全是負數的情況 maxn = max(x, maxn); else now = 0; } else //加上 x 之後 now>0 now += x; // 因為 x 是負數,所以沒必要更新ans } } printf("%lld\n", maxn); } return 0; }