【問題描述】
對於乙個字串s,我們定義s的分值f(s)為s中恰好出現一次的字元個數。例如f(「aba」) =1,f(「abc」)= 3, f(「aaa」) =0。
現在給定乙個字串s 0…n - 1,請你計算對於所有s的非空子串s[i…j](0≤is j 這道題咋說呢,我開始看的時候感覺很難,但是只要你理解了感覺也很簡單了
我開始想到的是用窮舉的方法把每個子串提出來,然後再判斷出現一次的字元個數,但是顯然發現這個方法光是列出所有的子串
的時間複雜度都是o(n的平方),當輸入的字串太長就很難算出來了,所有想到下面的方法:
我們以「ababc」為例:
其子串有: a 1
a b 2
a b a 1
a b a b 0
a b a b c 1
b 1b a 2
b a b 1
b a b c 2
a 1a b 2
a b c 3
b 1b c 2
c 1當我們豎著以列觀察會發現單個出現的那個字母意思是前面和後面都沒有,換而言之算單獨出現的那個字母一定在和它一樣的前乙個字母和後面一樣的那個字母之間,我們就可以理解為那個字母的貢獻值,所以乙個思路就出來了:乙個字母乙個字母的來看,看看它的貢獻值是多少,然後吧所有的字母的貢獻值加起來就行了。這個方法的時間複雜度為o(n),所有比較合理。
那麼每個字母的貢獻值怎麼算呢?其實也就是它前面最近一次出現的位置到這次的距離乘上這次到後面最近一次出現這個字母的距離(這個我當時理解了好久,可能是我基礎不夠吧!也可能是我腦子笨!哈哈哈)
然後想辦法的用**算出來(下面**有注釋,不懂的話多看看應該就懂了)
/* 子串分值 */
#include
using
namespace std;
#include
#include
intmain()
for(
int i =
0; i <
26; i++
) late[i]
= n;
//下面同理,只是求後面的最近的乙個,
for(
int i = n-
1; i >-1
; i--
)for
(int i =
0; i < n; i++
) cout <
return0;
}
#include
using
namespace std;
#include
int pre[
1000001]=
;int last[
100001]=
;int
main()
for(
int i =
0; i <=
26; i++
) late[i]
= n;
for(
int i = n-
1; i >-1
; i--
)for
(int i =
0; i < n; i++
) cout
}
另外這只是思路,我沒有注意cpu和記憶體的限制情況,只考慮時間複雜度了,以後會注意的哈,不過思路真正的懂了那些都是小兒科。
我接下來到藍橋杯 比賽這段時間盡量每天做一道往年題目或者找到合適的發上來,一方面監督自己,一方面求大佬指正,希望一起進步一起學習哈!!!
藍橋杯大賽 每日一題(2 子串分值和)
我的思路 在做這道題之前我因為做過和這類似的子串分值 include using namespace std include include intmain ret st.size st.clear cout return0 這個我只是想到c 的set容器的用法,所以無聊寫的,簡單,但是也很容易超時...
藍橋杯每日一題(1) 高斯日記(python)
topic 大數學家高斯有個好習慣 無論如何都要記日記。他的日記有個與眾不同的地方,他從不註明年月日,而是用乙個整數代替,比如 4210 後來人們知道,那個整數就是日期,它表示那一天是高斯出生後的第幾天。這或許也是個好習慣,它時時刻刻提醒著主人 日子又過去一天,還有多少時光可以用於浪費呢?高斯出生於...
藍橋杯 每日一題 Sine之舞
最近fj為他的奶牛們開設了數學分析課,fj知道若要學好這門課,必須有乙個好的三角函式基本功。所以他準備和奶牛們做乙個 sine之舞 的遊戲,寓教於樂,提高奶牛們的計算能力。不妨設an sin 1 sin 2 sin 3 sin 4 sin n sn a1 n a2 n 1 a3 2 an 1 fj想...